Compare commits

...

246 commits

Author SHA1 Message Date
Ruledo
11d6d3deda Update foxbuntu-builder.sh
Moved pico repo
2025-05-14 00:32:15 -07:00
noon92
6f16acfae1
Merge pull request #411 from femtofox/noon2
Combined meshtastic wifi sync and avahi daemon service managers into a single function
2025-04-25 21:06:49 +03:00
nagumii
df8cb48983 Combined meshtastic wifi sync and avahi daemon service managers into a single function 2025-04-25 21:06:26 +03:00
noon92
64eaf03236
Merge pull request #410 from femtofox/noon2
Add avahi-daemon toggle to networking menu
2025-04-25 16:00:27 +03:00
nagumii
2a3f96ed70 Add avahi-daemon toggle to networking menu 2025-04-25 16:00:02 +03:00
noon92
3d053a5c6f
Merge pull request #409 from femtofox/main
Update noon2
2025-04-25 15:28:30 +03:00
noon92
08de3d0cb8
Merge pull request #408 from femtofox/noon2
Prettify runounce output
2025-04-25 15:28:00 +03:00
noon92
7e52f44f3c
Merge pull request #404 from jeremy-asher/add-tun-module-dependency
add tun module dependency
2025-04-21 20:28:23 +03:00
Jeremy Asher
419f203f57 add tun module dependency
This adds `NET_CORE` which is a dependency for `TUN`.
2025-04-18 11:21:40 -07:00
Tom
ccdb98a113
Update README.md 2025-03-24 00:35:38 +00:00
nagumii
2b1ffd0d90 Prettify runounce output 2025-03-15 19:51:40 +02:00
Tom
6c3b0da71f
Update README.md 2025-03-15 00:35:04 +00:00
noon92
1fd343fadf
Merge pull request #391 from femtofox/noon2
Increment foxbuntu release
2025-03-14 18:08:25 +02:00
nagumii
a4b8ba374d Increment foxbuntu release 2025-03-14 18:08:10 +02:00
noon92
9242ab9bc7
Merge pull request #390 from femtofox/noon2
Fix meshtastic install/upgrade in menus
2025-03-14 17:18:06 +02:00
nagumii
673cd7e268 Fix meshtastic install/upgrade in menus 2025-03-14 17:17:27 +02:00
noon92
0540668e19
Merge pull request #389 from femtofox/noon2
Fix software install/upgrade exit status false reports
2025-03-14 17:14:56 +02:00
nagumii
357d6fe77a Fix software install/upgrade exit status false reports 2025-03-14 17:14:01 +02:00
Tom
dbcbba4402
Merge pull request #387 from Jorropo/patch-1
fix tindie 404 link in README.md
2025-03-13 14:45:49 +00:00
Jorropo
253d10b8bf
fix tindie 404 link in README.md 2025-03-13 15:43:41 +01:00
noon92
c20eaa469c
Merge pull request #386 from femtofox/noon2
Fix "run software" command in software menu, re-enable for Contact and Control
2025-03-08 18:34:19 +02:00
nagumii
6b3245b554 Update contact_client.sh 2025-03-08 18:33:40 +02:00
nagumii
3997de8c87 Fix "run software" command in software menu, re-enable for Contact and Control 2025-03-08 18:33:01 +02:00
noon92
b7bc76a9ac
Merge pull request #385 from femtofox/main
Update noon2 from main
2025-03-08 18:30:46 +02:00
noon92
9a2fbb40b8
Merge pull request #384 from femtofox/noon2
try prevent daily updates
2025-03-08 16:48:39 +02:00
nagumii
5120cba1a6 try prevent daily updates 2025-03-08 16:47:59 +02:00
noon92
1eaab50281
Merge pull request #383 from femtofox/settings_overhaul_control
Prevent conflicts between Control for Meshtastic and running BBS applications
2025-03-05 23:59:47 +02:00
nagumii
7d34cd9b61 Prevent conflicts between Control for Meshtastic and running BBS applications 2025-03-05 23:58:41 +02:00
nagumii
6c6a7218a8 add pip install of control for meshtastic requirements to chroot 2025-03-05 22:51:23 +02:00
noon92
cfbce79724
Merge pull request #382 from femtofox/settings_overhaul_control
+x for control software package
2025-03-05 22:37:06 +02:00
nagumii
f8e2355e79 +x for control software package 2025-03-05 22:36:40 +02:00
noon92
52f92ffdb8
Merge pull request #381 from femtofox/settings_overhaul_control
Revamp settings menu to take advantage of Control by @pdxlocations
2025-03-05 20:28:40 +02:00
nagumii
978d58d649 Add control package to software menu 2025-03-05 20:26:38 +02:00
nagumii
fc7f187937 Add control download to chroot 2025-03-05 20:07:56 +02:00
nagumii
436856abcd Revamp settings menu to take advantage of Control by pdxlocations 2025-03-05 20:04:37 +02:00
noon92
89d10194bb
Merge pull request #380 from femtofox/noon2
Fix wifi toggle on button press
2025-03-04 12:46:42 +02:00
nagumii
242a145bdb Fix wifi toggle on button press 2025-03-04 12:44:48 +02:00
noon92
cb92aa7b18
Merge pull request #379 from femtofox/main
update noon2
2025-03-03 19:38:13 +02:00
noon92
c4a703c172
Update femto-config 2025-03-03 19:37:22 +02:00
noon92
e464fc7507
Update femtofox-config.txt 2025-03-03 19:32:28 +02:00
noon92
0466655eff
Merge pull request #378 from femtofox/noon2
Add meshtastic i2c support to menus and usb-config
2025-03-03 19:31:15 +02:00
noon92
95bf58eb48
Merge branch 'main' into noon2 2025-03-03 19:31:09 +02:00
nagumii
8e4895320e Add meshtastic i2c support to menus. 2025-03-03 19:30:46 +02:00
Ruledo
f5a903cfe6 Foxbuntu Build Script Documentation
This is how we build the releases.
2025-03-03 00:16:12 -08:00
noon92
17ea7f770d
Merge pull request #374 from femtofox/noon2
Add TUN as kernel module
2025-03-02 00:14:02 +02:00
nagumii
97ba36396b Add Tun 2025-03-01 23:56:44 +02:00
noon92
cc66ac4e34
Merge pull request #372 from femtofox/noon2
Minor fix for system info > OS info
2025-02-27 13:35:01 +02:00
nagumii
81309bf271 Minor fix for system info > OS info 2025-02-27 13:34:45 +02:00
noon92
563160d522
Merge pull request #371 from femtofox/noon2
Increment foxbuntu version
2025-02-26 20:07:47 +02:00
nagumii
e74b48af6b Increment foxbuntu version 2025-02-26 20:07:15 +02:00
noon92
dbaebb6b23
Merge pull request #370 from femtofox/noon2
Add retry to usb-config-tool software installation
2025-02-26 19:17:24 +02:00
nagumii
b04080efb5 Prevent Boot Complete LED boot code until USB-config is done 2025-02-26 19:17:00 +02:00
nagumii
dd420e146e Add retry to usb-config-tool software installation
Will retry up to 5 times
2025-02-26 19:16:12 +02:00
noon92
fb33c3af1d
Merge pull request #369 from femtofox/noon2
Fix usb-config config first boot check
2025-02-26 18:09:16 +02:00
nagumii
94ae7aaa1b Update femto-usb-config-tool.sh 2025-02-26 16:41:17 +02:00
noon92
7c36111d6c
Merge pull request #368 from femtofox/noon2
Add software installation to femto-config.txt example file
2025-02-26 16:37:14 +02:00
nagumii
3fe7984082 Update femtofox-config.txt 2025-02-26 16:36:55 +02:00
noon92
753d216999
Merge pull request #367 from femtofox/noon2
Add software install via USB config tool
2025-02-26 16:16:20 +02:00
nagumii
119b4ef039 Update femtofox-config.txt 2025-02-26 16:16:07 +02:00
nagumii
5c7e392c95 Add software install via USB config tool 2025-02-26 16:08:40 +02:00
Ruledo
73788c1b84 Build on any OS
Good luck.
2025-02-25 00:12:36 -08:00
noon92
5d2394b0b0
Merge pull request #366 from femtofox/noon2
Add new meshing-around dependencies
2025-02-24 22:46:56 +02:00
nagumii
581236ad7b Add new meshing-around dependencies 2025-02-24 22:46:26 +02:00
noon92
70ce2d8eb7
Merge pull request #365 from femtofox/noon2
Fix meshtastic_cli support
2025-02-23 15:52:40 +02:00
nagumii
0cdd6f7125 Fix meshtastic_cli support 2025-02-23 15:52:25 +02:00
noon92
5a80480095
Merge pull request #364 from femtofox/noon2
Add meshtastic_cli to usb config tool
2025-02-23 14:37:50 +02:00
nagumii
4550289068 Add meshtastic_cli to usb config tool 2025-02-23 14:37:33 +02:00
noon92
5e018368a0
Update README.md 2025-02-22 20:01:06 +02:00
noon92
cd52e21cd5
Merge pull request #361 from femtofox/noon2
Fix small pinouts issues
2025-02-20 00:33:10 +02:00
nagumii
ff37008b0f Fix small pinouts issues 2025-02-20 00:32:41 +02:00
noon92
b86f52c830
Merge pull request #359 from femtofox/noon2
Missing " in runonce
2025-02-19 20:39:19 +02:00
nagumii
80fa90e120 Missing " in runonce 2025-02-19 20:39:02 +02:00
noon92
89a302d024
Merge pull request #358 from femtofox/noon2
Fix typo in lora settings menu
2025-02-19 14:35:06 +02:00
nagumii
21519c0345 Fix typo in lora settings menu 2025-02-19 14:34:42 +02:00
noon92
8b4e251b5c
Merge pull request #357 from femtofox/noon2
Default routes auto update more reliably (thanks @Ruledo)
2025-02-19 14:18:20 +02:00
nagumii
9db705447e disable ttyd in chroot and re-enable on first boot 2025-02-19 14:14:38 +02:00
nagumii
01b65a6424 Update femto-runonce.sh 2025-02-19 13:50:27 +02:00
nagumii
a980af7e47 add back ssh keygen 2025-02-19 13:49:53 +02:00
nagumii
883d57a3e7 Network failover 2025-02-19 13:24:32 +02:00
Tom
0850c60fd1
Update README.md 2025-02-19 02:50:51 +00:00
Tom
3a06244174
Update README.md 2025-02-19 01:21:49 +00:00
noon92
064a8b726c
Merge pull request #353 from femtofox/noon2
add jq and rsync to apt installs in chroot
2025-02-19 01:03:58 +02:00
nagumii
9aabaad7d5 add jq and rsync to apt installs in chroot 2025-02-19 01:03:08 +02:00
noon92
8fa643408a
Merge pull request #352 from femtofox/main
Update from main
2025-02-19 01:01:29 +02:00
noon92
f205eebb05
Merge pull request #346 from joshbowyer/patch-10
Update femtofox.chroot
2025-02-19 01:00:54 +02:00
noon92
d7bdf64a2f
Merge pull request #351 from femtofox/noon2
Only generate new ttyd ssl keys if hostname actually changed
2025-02-19 01:00:39 +02:00
nagumii
368adf0641 Only generate new ttyd ssl keys if hostname actually changed 2025-02-19 01:00:04 +02:00
Tom
9019527e95
Update README.md 2025-02-18 22:51:35 +00:00
noon92
f2e8ad0491
Merge pull request #350 from femtofox/noon2
Revamp meshtastic settings ingest
2025-02-18 22:27:21 +02:00
nagumii
ee461842ec Revamp settings ingest 2025-02-18 21:16:33 +02:00
nagumii
3fc3c50f9a Continue refining lora settings menu 2025-02-17 22:35:40 +02:00
noon92
a5eef81248
Merge pull request #347 from femtofox/noon2
Revert runonce swapfile
2025-02-17 19:43:27 +02:00
nagumii
aaaa7d9e87 Revert runonce swapfile
"oops"
2025-02-17 19:43:09 +02:00
joshbowyer
8f0d52117e
Update femtofox.chroot
Add vim and mtd-utils to apt install in chroot
2025-02-17 11:33:47 -06:00
nagumii
57954fe236 Update femto-set-time.sh 2025-02-17 17:37:12 +02:00
nagumii
2c2edf0516 Update femto-set-time.sh 2025-02-17 17:31:10 +02:00
noon92
6481653ad8
Merge pull request #345 from femtofox/noon2
Fix set-time dialog
2025-02-17 15:04:35 +02:00
nagumii
f9977f68a2 Fix set-time dialog 2025-02-17 15:04:15 +02:00
noon92
c212a3db80
Merge pull request #344 from femtofox/noon2
Enable Meshtastic webserver on port 443
2025-02-17 12:49:33 +02:00
nagumii
793aa33869 Enable Meshtastic webserver on port 443 2025-02-17 12:48:04 +02:00
noon92
90651c52c9
Merge pull request #343 from femtofox/noon2
Major improvements to LoRa configuration menus
2025-02-16 23:19:51 +02:00
nagumii
5db521a409 Update femto-meshtasticd-lora-dialogs.sh 2025-02-16 23:19:18 +02:00
nagumii
0d71573975 Continued work on lora settings menu 2025-02-16 17:38:03 +02:00
nagumii
ef7a938f76 Fix compatibility with install wizard 2025-02-16 15:04:05 +02:00
nagumii
7c73c1ed16 Merge branch 'noon2' of https://github.com/femtofox/femtofox into noon2 2025-02-16 14:57:00 +02:00
nagumii
1e6aa868e0 Major improvements to LoRa configuration menus 2025-02-16 14:56:57 +02:00
noon92
39ef5b7856
Merge pull request #342 from femtofox/noon2
Change femto-runonce service to self-disable after first boot
2025-02-16 11:29:03 +02:00
noon92
f3fff87fca
Merge branch 'main' into noon2 2025-02-16 11:28:43 +02:00
nagumii
95d20fb8ba Change femto-runonce service to self-disable after first boot 2025-02-16 11:27:58 +02:00
Tom
4cbc597b1f
Update README.md 2025-02-16 01:56:51 +00:00
noon92
5348b1482c
Merge pull request #341 from femtofox/noon2
Fix typo in legacy admin menu
2025-02-16 00:02:13 +02:00
nagumii
d09b299875 Fix typo in legacy admin menu 2025-02-16 00:01:56 +02:00
noon92
2a6fc16e4e
Merge pull request #340 from femtofox/noon2
Massive overhaul of LoRa settings menus
2025-02-15 23:02:05 +02:00
nagumii
0e0316d362 Update femto-meshtasticd-lora-dialogs.sh 2025-02-15 22:55:34 +02:00
nagumii
e585c88882 Update .dialogrc 2025-02-15 22:41:51 +02:00
nagumii
083110a264 Overhaul of LoRa settings menus 2025-02-15 22:41:44 +02:00
noon92
fc023f695f
Merge pull request #338 from femtofox/noon2
Prettify the service status utility
2025-02-14 20:06:19 +02:00
nagumii
6d1b7ecc5b Prettify the service status utility 2025-02-14 20:05:59 +02:00
noon92
031e056c0e
Merge pull request #337 from femtofox/noon2
Fix Foxbuntu version display method
2025-02-14 18:31:12 +02:00
nagumii
1ea75dd079 Fix Foxbuntu version display method 2025-02-14 18:02:21 +02:00
noon92
29d9625cfa
Merge pull request #336 from femtofox/noon2
Fix typo in #330
2025-02-14 15:55:20 +02:00
nagumii
828f27992e Fix small issue with #330 2025-02-14 15:54:56 +02:00
noon92
86de5cd0ab
Merge pull request #335 from femtofox/noon2
Temporarily remove "Run software" from software manager package menu due to bug #326
2025-02-14 14:15:10 +02:00
nagumii
d52e26def2 Final touches 2025-02-14 14:13:30 +02:00
nagumii
35128e204e Temporarily remove "Run software" from software manager package menu due to bug #326 2025-02-14 13:57:12 +02:00
noon92
ed65be5879
Merge pull request #334 from femtofox/noon2
Improve installation usability by allowing pip installs to display live on screen
2025-02-14 13:43:55 +02:00
nagumii
01da3ccd36 Improve installation usability by allowing pip installs to display live on screen 2025-02-14 13:43:28 +02:00
noon92
1270ba504d
Merge pull request #333 from femtofox/noon2
Improve UX for blacklisting function in kernel modification manager
2025-02-14 13:27:58 +02:00
nagumii
104c8cf656 spit and polish 2025-02-14 13:20:24 +02:00
nagumii
d7b822c7b1 Improve UX for blacklisting function in kernel modification manager 2025-02-14 11:23:24 +02:00
noon92
39444ad634
Merge pull request #332 from femtofox/noon2
Increment Foxbuntu release to 1.0
2025-02-14 10:38:27 +02:00
nagumii
af8bdab446 Increment Foxbuntu release to 1.0 2025-02-14 10:37:59 +02:00
nagumii
97d10e8a35 Tidy up runonce 2025-02-14 10:36:08 +02:00
noon92
784e5e5f44
Merge pull request #331 from femtofox/main
Update noon2
2025-02-14 10:34:03 +02:00
noon92
4852b4057c
Merge pull request #330 from femtofox/noon2
Prevent login prompt from appearing until boot is complete
2025-02-14 10:19:16 +02:00
nagumii
989ffdbfd7 Prevent login prompt from appearing until boot is complete
Written by @Ruledo
2025-02-14 10:18:41 +02:00
noon92
bf58b66b3e
Merge pull request #329 from femtofox/OSC
wrong arg in getting private key in femto-config
2025-02-14 10:00:50 +02:00
Ruledo
a7ace1c758 wrong arg in getting private key in femto-config
Just a typo in the menu
2025-02-13 16:06:44 -08:00
Ruledo
822485e6aa
Merge pull request #328 from femtofox/OSC
Fixed compiler.  Removed apt cleanout from build.
2025-02-13 15:20:44 -08:00
Ruledo
b74db8055f Merge branch 'OSC' of https://github.com/femtofox/femtofox into OSC 2025-02-13 14:21:57 -08:00
Ruledo
9ad001f5e1 Backup and restore libc_nonshared.a and correct paths
libgcc wasn't playing nice after build.sh got a hold of it.
This preserves the compiler.
2025-02-13 14:21:48 -08:00
Ruledo
74af9894d9 backing up libc_nonshared.a before build.
cp /usr/lib/arm-linux-gnueabihf/libc_nonshared.a /usr/lib/arm-linux-gnueabihf/libc_nonshared.a.keep
Because build.sh kills it and we need it.
2025-02-13 14:03:24 -08:00
noon92
9882d3e0d0
Merge pull request #323 from femtofox/OSC
Watchclock Dog checks if meshtasticd is running
2025-02-13 23:30:39 +02:00
noon92
4f7c392ae6
Change sleep time to 30 2025-02-13 23:30:19 +02:00
noon92
f9bb77b26e
Merge pull request #325 from femtofox/noon2
Revamp of kernel module menu, adding blacklist and better UI
2025-02-13 22:26:47 +02:00
nagumii
70196d7134 Revamp of kernel module menu, adding blacklist and better UI 2025-02-13 21:41:16 +02:00
noon92
abac1e33cb
Merge pull request #320 from femtofox/eth0_test
Use eth0 mac address for meshtasticd
2025-02-13 15:02:11 +02:00
noon92
6600f73d12
Merge pull request #324 from femtofox/noon2
Revamp kernel module manager
2025-02-13 13:46:20 +02:00
nagumii
3cb06aeb91 Revamp kernel module manager 2025-02-13 13:45:58 +02:00
noon92
f689b8ba20
Update femto-kernel-modules.sh 2025-02-13 13:44:36 +02:00
nagumii
7ed3a99ee4 Revamp kernel module manager 2025-02-13 13:42:53 +02:00
nagumii
0ce3fb1535 remove debug line 2025-02-12 22:15:37 +02:00
nagumii
e0fa55a4d1 Merge branch 'eth0_test' of https://github.com/femtofox/femtofox into eth0_test 2025-02-12 22:09:05 +02:00
nagumii
7bf723d62d fix a couple service Afters 2025-02-12 22:09:01 +02:00
Ruledo
ed80e931de Watchclock Dog checks if meshtasticd is running
While loop checks if meshtasticd is running and if not nopes out until next loop.
2025-02-12 11:38:41 -08:00
nagumii
298c545cfa Update femto-runonce.sh 2025-02-12 21:36:20 +02:00
noon92
db6574790a
Merge pull request #322 from femtofox/main
Merge main to eth0
2025-02-12 21:32:45 +02:00
nagumii
60f2432c69 Update femtofox.chroot 2025-02-12 21:09:20 +02:00
noon92
bcd8ec366f
Merge pull request #321 from femtofox/noon2
Fix ssl keygen for ttyd package
2025-02-12 20:08:17 +02:00
nagumii
85f959b1a3 Fix ssl keygen for ttyd package 2025-02-12 20:07:45 +02:00
nagumii
d2d2fd9cbe Update override.conf 2025-02-12 19:22:59 +02:00
nagumii
e337ed62ae Switch source of meshtasticd mac address to eth0 2025-02-12 18:42:37 +02:00
nagumii
d83944862a Clean up license display 2025-02-12 17:54:55 +02:00
noon92
c51ffabb57
Merge pull request #319 from femtofox/main
merge main to noon2
2025-02-12 17:48:53 +02:00
nagumii
83e5891645 Update femto-software.sh 2025-02-12 17:48:06 +02:00
nagumii
eb914176b8 Update femto_package_template.sh 2025-02-12 16:46:23 +02:00
nagumii
d80265fd7c maintainer helptext fix 2025-02-12 16:44:21 +02:00
noon92
01f090316d
Merge pull request #318 from femtofox/noon2
Small refactor of software packages
2025-02-12 16:32:31 +02:00
nagumii
c14624fca9 More changes to packages 2025-02-12 16:31:56 +02:00
nagumii
1486a39675 package manager modifications 2025-02-12 14:01:01 +02:00
noon92
142fe6f29f
Update femto-config 2025-02-11 23:18:57 +02:00
noon92
39e5973cc7
Merge pull request #316 from femtofox/noon2
Add Meshtastic wifi sync management menu in networking
2025-02-11 23:17:59 +02:00
nagumii
987d56955c Add Meshtastic wifi sync management menu in networking 2025-02-11 23:17:33 +02:00
noon92
140b770317
Merge pull request #315 from femtofox/noon2
Fix new service descriptions
2025-02-11 21:08:33 +02:00
nagumii
875b7e3f08 Fix new service descriptions 2025-02-11 21:06:52 +02:00
noon92
d8c28c1263
Merge pull request #314 from femtofox/noon2
Tidy up runonce
2025-02-11 15:13:59 +02:00
nagumii
abae18a4bd Tidy up runonce 2025-02-11 15:13:30 +02:00
noon92
4147676af4
Merge pull request #313 from femtofox/noon2
Move all femto services to /etc/systemd/system
2025-02-10 23:57:02 +02:00
nagumii
8168aa5628 Add software license name to software description 2025-02-10 23:55:44 +02:00
nagumii
a79f0750b0 Move all femto services to /etc/systemd/system 2025-02-10 23:37:38 +02:00
noon92
009b158182
Merge pull request #310 from femtofox/OSC
wifi mesh control and watchclock-dog
2025-02-10 23:10:32 +02:00
noon92
1bfb13a35c
Merge pull request #311 from pdxlocations/escape-escape
Double escape special chars in override.conf
2025-02-10 23:10:20 +02:00
pdxlocations
f591a19481 double escape special chars 2025-02-10 13:02:02 -08:00
noon92
96060c8804
Merge pull request #302 from femtofox/sfc-alias
Add SFC alias to bash_aliases at firstrun
2025-02-10 22:44:23 +02:00
noon92
8a8193a87b
Update femto-wifi-mesh-control.service 2025-02-10 22:40:01 +02:00
noon92
9f46e22725
Update femto-watchclock-dog.service 2025-02-10 22:31:55 +02:00
Ruledo
abd6995d95 femto-wifi-mesh-control and femto-watchclock-dog
enable services in chroot
2025-02-10 11:35:57 -08:00
Ruledo
0b64bbefa7 Missed +x
oops.
2025-02-10 11:31:21 -08:00
Ruledo
5876ced494 wifi mesh control and watchclock-dog
Renamed wifi-mesh-control and now checks for meshtasticd to be running.
Also removed wants from service to prevent starting meshtasticd.
Added femto-watchclock-dog that checks for large time changes and restarts meshtasticd if detected to prevent a state where meshtasticd is running but not responsive on api port.
2025-02-10 11:26:55 -08:00
noon92
5d1518bd91
Update femto-runonce.sh 2025-02-10 20:39:18 +02:00
Tom
4926254b40
Revert 00-header 2025-02-10 18:28:42 +00:00
noon92
fd52c30427
Merge pull request #308 from femtofox/noon
Check if meshtasticd service is running before trying to interact with it, and offer to launch the service if not
2025-02-10 18:15:56 +02:00
nagumii
4f16844e83 Check if meshtasticd service is running before trying to modify settings 2025-02-10 18:13:39 +02:00
nagumii
8898c1137d Update femto-config 2025-02-10 01:14:46 +02:00
noon92
e0a5ab1f4b
Merge pull request #305 from femtofox/noon
Fix small niggling error in sysinfo cpu
2025-02-10 01:13:35 +02:00
nagumii
3ad68460f0 Fix small niggling error in sysinfo cpu 2025-02-10 01:12:48 +02:00
nagumii
4316bd2c88 Create rv1106-luckfox-pico-ultra-ipc.dtsi 2025-02-09 19:03:39 +02:00
noon92
ef17960a7c
Merge pull request #303 from femtofox/revert-294-OSC
This was merged accidentally
2025-02-09 18:58:40 +02:00
noon92
7d5b8be309
Revert "time-monitor service to restart meshtasticd" 2025-02-09 18:58:21 +02:00
Tom
48f4bec539
Update 00-header 2025-02-09 00:43:04 +00:00
Tom
9799a4709f
Add SFC alias to bash_aliases at firstrun
because 14 extra characters is too much.
2025-02-09 00:30:16 +00:00
noon92
33dd9f1d0e
Merge pull request #301 from femtofox/main
Update noon from main
2025-02-09 00:36:57 +02:00
noon92
1ee196aaa6
Merge pull request #300 from femtofox/noon
Update femto-utils.sh
2025-02-09 00:36:32 +02:00
noon92
50a0936849
Merge pull request #299 from femtofox/new_working
Further improve granularity
2025-02-09 00:34:24 +02:00
nagumii
99dcac2b66 Create rv1106-luckfox-pico-ultra-ipc.dtsi 2025-02-09 00:33:22 +02:00
noon92
986210021f
Merge branch 'main' into new_working 2025-02-09 00:31:07 +02:00
noon92
f6b5767b28
Merge pull request #298 from femtofox/revert-295-OSC
Revert "Update new_working from OSC"
2025-02-09 00:27:05 +02:00
noon92
a995399774
Revert "Update new_working from OSC" 2025-02-09 00:26:55 +02:00
nagumii
2746e23523 Update femto-utils.sh 2025-02-09 00:26:12 +02:00
noon92
a71d4bd1dd
Merge pull request #296 from femtofox/noon
Improve granularity of service status utility in femto-utils.sh
2025-02-08 19:23:22 +02:00
nagumii
412065a195 Improve granularity of service status utility in femto-utils.sh 2025-02-08 19:23:04 +02:00
nagumii
b543a11898 Improve service state utility in femto-utils.sh 2025-02-08 19:05:19 +02:00
nagumii
3b520405ff Fix femto-utils.sh help text 2025-02-08 18:00:13 +02:00
nagumii
8879717914 Merge branch 'new_working' of https://github.com/femtofox/femtofox into new_working 2025-02-08 14:48:43 +02:00
noon92
d1374f6242
Merge pull request #295 from femtofox/OSC
Update from OSC
2025-02-08 14:47:44 +02:00
Ruledo
bad1ddc204 time-monitor service to restart meshtasticd
Currently set to detect a 1 week change in time.
2025-02-07 20:26:41 -08:00
nagumii
d8cc314662 License button should only show for installed packages 2025-02-08 04:02:06 +02:00
noon92
34755aeeb5
Merge pull request #293 from femtofox/new_working
add ttyd license to /opt/ttyd
2025-02-08 03:01:42 +02:00
nagumii
921634eeb2 add ttyd license to /opt/ttyd 2025-02-08 03:00:27 +02:00
noon92
29318c8a4d
Merge pull request #292 from femtofox/new_working
ttyd.sh +x
2025-02-08 02:38:55 +02:00
nagumii
6c2a010189 +x 2025-02-08 02:38:09 +02:00
noon92
fe8d049fb4
Merge pull request #291 from femtofox/new_working
Revamp software menu system and improve package manager
2025-02-08 02:24:59 +02:00
nagumii
db764c4612 Revamp software menu system and improve package manager 2025-02-08 02:23:38 +02:00
noon92
2f4f085620
Merge pull request #290 from femtofox/new_working
Update LICENSE
2025-02-08 02:22:50 +02:00
nagumii
5212649d94 Delete ttyd.sh 2025-02-08 02:22:28 +02:00
nagumii
82a980498b undo 2025-02-08 02:21:33 +02:00
nagumii
f907dfad5f add pip install -r requirements.txt to meshing_around, tc2_bbs, contact 2025-02-08 02:16:22 +02:00
nagumii
efd5adc63e Add license button to package installer 2025-02-08 00:54:25 +02:00
nagumii
e0cc5ddc6c Update femto-software.sh 2025-02-07 22:02:44 +02:00
nagumii
038da36ccd Refactor of parts of package manager, move ttyd to package manager, move check-service-status to utils 2025-02-07 21:51:38 +02:00
nagumii
af9b7b42bd Merge branch 'new_working' of https://github.com/femtofox/femtofox into new_working 2025-02-07 17:15:35 +02:00
nagumii
07e387f1e0 Change Foxbuntu license to GPL3 2025-02-07 17:03:16 +02:00
noon92
0672889f8e
Update LICENSE
This changes the Foxbuntu license to GPL3
2025-02-07 16:40:17 +02:00
noon92
52964d23c8
Merge pull request #286 from joshbowyer/patch-9
Create rv1106-luckfox-pico-ultra-ipc.dtsi
2025-02-07 16:39:11 +02:00
noon92
05c7cbcfc3
Merge pull request #289 from femtofox/new_working
Show install status of package in software menu
2025-02-07 16:38:46 +02:00
nagumii
f4167e20d3 Show install status of package in software menu 2025-02-07 12:41:13 +02:00
noon92
521b8d6e37
Merge pull request #288 from femtofox/new_working
Improve wizard and set-time UX
2025-02-07 01:00:11 +02:00
nagumii
f5a7303046 Improve wizard and set-time UX 2025-02-07 00:59:38 +02:00
joshbowyer
7ab27dabbd
Create rv1106-luckfox-pico-ultra-ipc.dtsi
Fix SPI pin conflict for Ultra W
2025-02-06 12:46:17 -06:00
noon92
33306b89d0
Merge pull request #285 from femtofox/new_working
Disable daily unattended upgrade that somehow got enabled
2025-02-06 18:07:53 +02:00
nagumii
a66a97e2a9 Disable daily unattended upgrade that somehow got disabled 2025-02-06 18:07:18 +02:00
noon92
d206776998
Merge pull request #284 from femtofox/new_working
Tidy up install wizard
2025-02-06 15:11:37 +02:00
nagumii
e0cb49db40 Tidy up install wizard 2025-02-06 15:10:34 +02:00
noon92
2c8643b3f8
Merge pull request #283 from femtofox/new_working
Change menu colors a bit to make clearer in web terminal
2025-02-06 15:10:12 +02:00
nagumii
ca22939701 Update .dialogrc 2025-02-06 14:44:06 +02:00
nagumii
c799f55703 Change menu colors a bit to make clearer in web terminal 2025-02-06 14:41:17 +02:00
65 changed files with 4127 additions and 4772 deletions

685
LICENSE
View file

@ -1,3 +1,10 @@
Femtofox is comprised of two projects, with two different licenses:
1. Femtofox - the hardware, which is licensed "CC BY-NC-ND - noncommercial". Summary: you may copy and share and modify the hardware files, but cannot sell them without license from Femtofox, and must give attribution to Femtofox.
2. Foxbuntu - refers to the modifications to Ubuntu made as part of the Femtofox project, which is licensed GNU GPLv3. Summary: you may use, modify and distribute (including for commercial purposes) Foxbuntu, but must give attribution to Femtofox and distribute this license with your project. Any modified version must remain open source.
See below for the full license texts.
Hardware (Femtofox) license:
Summary:
Attribution — You must give appropriate credit , provide a link to the license, and indicate if changes were made . You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
NonCommercial — You may not use the material for commercial purposes .
@ -408,3 +415,681 @@ the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.
Software (Foxbuntu) license:
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View file

@ -1,18 +1,27 @@
<img src="assets/images/KSE_side_shot.png" width="750">
# Femtofox &nbsp;&nbsp;&nbsp;<sub><sub>The tiny, low power Linux Meshtastic node
### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Click here for the Femtofox store](https://www.etsy.com/listing/1861858340/femtofox-pro-v1-kit-compact-arm-linux)
**Femtofox is a Linux-based mesh development platform - a Raspberry Pi sized computer with onboard LoRa radio, capable of being run with only 0.3w, making it *ideal* for solar powered nodes.**
The Luckfox Pico Mini is the postage stamp sized heart of the Femtofox - a compact and power efficient Linux board, running a customized version of Ubuntu. Femtofox is an expansion of the Luckfox's capabilities, utilizing a custom PCB with a 30db LoRa radio (over 6x the transmit power of a RAK Wisblock or Heltec V3) to create a power efficient, tiny and highly capable Meshtastic Linux node.
The Luckfox Pico Mini is the postage stamp sized heart of the Femtofox - a compact and power efficient Linux board, running Foxbuntu, our own customized version of Ubuntu. Femtofox is an expansion of the Luckfox's capabilities, utilizing a custom PCB with a 30db LoRa radio (over 6x the transmit power of a RAK Wisblock or Heltec V3) to create a power efficient, tiny and highly capable Meshtastic Linux node.
- [Features](#features)
- Specifications - coming soon
Find out more in the sections below, or in the [Wiki](https://github.com/femtofox/femtofox/wiki).
- [Features](#features) and [Specifications](#Specification)
- [Supported hardware](https://github.com/femtofox/femtofox/wiki/Supported-Hardware)
- [Installation guide](https://github.com/femtofox/femtofox/wiki/Getting-Started)
- How to order - coming soon
- How to order
- [Etsy (USA)](https://www.etsy.com/listing/1861858340/femtofox-pro-v1-kit-compact-arm-linux)
- [Tindie (UK)](https://www.tindie.com/products/nomdetom/femtofox-pro-v1-kit-linux-meshtastic-node/)
- [Etsy (UK)](https://www.etsy.com/uk/listing/1866094154/femtofox-pro-v1-kit-linux-meshtastic)
- [DIY instructions](https://github.com/femtofox/Femtofox_Community_Hardware)
- [USB configuration tool](https://github.com/femtofox/femtofox/wiki/USB-Config-Tool)
- [USB configuration tool](https://github.com/femtofox/femtofox/wiki/USB-Configuration-Tool)
- [Building your own Foxbuntu image](https://github.com/femtofox/femtofox/wiki/Building-Foxbuntu-%28WSL%29)
### Features
* Tiny size (63x54mm for Femtofox, 65x30mm for the Smol Edition). Equivalent to a standard Raspberry Pi hat and Pi Zero respectively.
@ -23,15 +32,33 @@ The Luckfox Pico Mini is the postage stamp sized heart of the Femtofox - a compa
* USB wifi support
* RTC support for timekeeping
### Specification
| Feature | Specification |
| ------------ | ------------------------------------------------------- |
| Processor | Rockchip RV1103, Cortex A7 \@1.1GHz |
| Memory | 64MB DDR2 |
| OS | Foxbuntu (based on Ubuntu 22.04.5 LTS Jammy) |
| Connectivity | USB 2.0 Host/Device |
| Network | RJ45 Ethernet with filtering<br> |
| | WiFi ready |
| GPIO | 17x GPIO pins (of which 8 are required for Lora module) |
| IO | 2x I2C JST PH |
| | 1x UART JST PH |
| Debug | 1x CH340 USB to serial adapter (Pro only) |
| Mesh | 30dB LoRa Radio 868-915MHz |
| Storage | Micro-SD slot |
| Power | 3.3-5V.dc via JST PH or USB-C |
| Dimensions | 63 x 54 x 19mm |
**Accomplished:**
- [x] Meshtastic native client controlling a LoRa radio (see [supported hardware](supported_hardware.md))
- [x] WIFI over USB (see [supported hardware](supported_hardware.md))
- [x] Ethernet over USB (see [supported hardware](supported_hardware.md))
- [x] Meshtastic native client controlling a LoRa radio (see [supported hardware](https://github.com/femtofox/femtofox/wiki/Supported-Hardware))
- [x] WIFI over USB (see [supported hardware](https://github.com/femtofox/femtofox/wiki/Supported-Hardware))
- [x] Ethernet over pins (see *Networking* below and wiring diagram at bottom of page)
- [x] UART communications with Meshtastic nodes (2 pin pairs) such as RAK Wisblock
- [x] USB serial communications with Meshtastic nodes (see [supported hardware](supported_hardware.md))
- [x] USB serial communications with Meshtastic nodes (see [supported hardware](https://github.com/femtofox/femtofox/wiki/Supported-Hardware))
- [x] USB mass storage
- [x] Real time clock (RTC) support (see [supported hardware](supported_hardware.md))
- [x] Real time clock (RTC) support (see [supported hardware](https://github.com/femtofox/femtofox/wiki/Supported-Hardware))
- [x] Activity LED disabled. User LED will blink for 5 seconds when boot is complete
- [x] Short pressing the "BOOT" button toggles wifi, 2-5 second press triggers reboot, 5+ second press shuts system down
- [x] Ability to reconfigure wifi via USB flash drive

View file

@ -18,9 +18,18 @@
## Options are "enable" and "disable"
#act_led="disable"
### Software installation
## Software package names are filenames (without .sh suffix) in /usr/local/bin/packages
## Multiple packages can be installed by separating them with commas
#software_install="packageA,packageB"
### Meshtastic settings
## Multiple meshtastic_cli lines can be added. This is important, as the Meshtastic CLI requires that different settings categories (such as device and lora) be handled in separate commands.
## See Meshtastic CLI docs (https://meshtastic.org/docs/software/python/cli/) for more information.
#meshtastic_cli="--set lora.modem_preset LONG_FAST"
#meshtastic_cli="--set device.role CLIENT"
## Radio module to use. Options are:
## "ebyte-e22-900m30s"
## "ebyte-e22-900m22s"
@ -48,6 +57,10 @@
#meshtastic_admin_key="XX="
#meshtastic_legacy_admin="false"
## Meshtastic i2c state.
## Enabling i2c without devices connected will lead to slowdowns and error messages.
## Options are "enable" and "disable"
meshtastic_i2c="disable"
### If the following line is uncommented, USB config will be skipped if a log file is present on the USB drive, indicating the tool has already been run on this system
#dont_run_if_log_exists

Binary file not shown.

View file

@ -23,7 +23,7 @@ ln -sf /usr/share/zoneinfo/UTC /etc/localtime
echo "Installing packages..."
apt update
DEBIAN_FRONTEND=noninteractive apt install -y --option Dpkg::Options::="--force-confold" linux-firmware wireless-tools git python3.10-venv libgpiod-dev libyaml-cpp-dev libbluetooth-dev openssl libssl-dev libulfius-dev liborcania-dev evtest screen avahi-daemon protobuf-compiler telnet fonts-noto-color-emoji ninja-build chrony qrencode software-properties-common python-is-python3 python3.10-venv lsof spi-tools python3-luma.oled samba
DEBIAN_FRONTEND=noninteractive apt install -y --option Dpkg::Options::="--force-confold" linux-firmware wireless-tools git python3.10-venv libgpiod-dev libyaml-cpp-dev libbluetooth-dev openssl libssl-dev libulfius-dev liborcania-dev evtest screen avahi-daemon protobuf-compiler telnet fonts-noto-color-emoji ninja-build chrony qrencode software-properties-common python-is-python3 python3.10-venv lsof spi-tools python3-luma.oled samba vim mtd-utils jq rsync
if [[ $? -eq 2 ]]; then echo "Error, step failed..."; fi
DEBIAN_FRONTEND=noninteractive apt upgrade -y --option Dpkg::Options::="--force-confold"
@ -39,7 +39,8 @@ DEBIAN_FRONTEND=noninteractive apt install -y --option Dpkg::Options::="--force-
echo "Installing dependencies for meshing-around and meshtastic cli..."
#pip config set global.extra-index-url https://www.piwheels.org/simple
pip3 install requests pyephem pytap2 meshtastic pypubsub geopy maidenhead beautifulsoup4 dadjokes schedule wikipedia googlesearch-python
pip3 install requests pyephem pytap2 meshtastic pypubsub geopy maidenhead beautifulsoup4 dadjokes schedule wikipedia googlesearch-python pubsub datetime
if [[ $? -eq 2 ]]; then echo "Error, step failed..."; fi
echo "Downloading ttyd and enabling service..."
@ -47,6 +48,12 @@ wget -qO- https://api.github.com/repos/tsl0922/ttyd/releases/latest | grep "brow
chmod +x /opt/ttyd/ttyd
systemctl enable ttyd
echo "Cloning Control for Meshtastic by pdxlocations"
git clone https://github.com/pdxlocations/control.git /opt/control
pip install -r /opt/control/requirements.txt
chown -R femto /opt/control
git config --global --add safe.directory /opt/control # prevents git error when updating
echo "Setting MOTD..."
mv /etc/update-motd.d/10-help-text /etc/update-motd.d/10-help-text.bak
mv /etc/update-motd.d/60-unminimize /etc/update-motd.d/60-unminimize.bak
@ -56,12 +63,18 @@ echo "femtofox" | tee /etc/hostname > /dev/null
echo "Configuring autostart of systemd services..."
systemctl enable button
systemctl enable meshtasticd
systemctl enable femto-runonce.service
systemctl enable femto-usb-config-tool.service
systemctl enable femto-boot-complete.service
systemctl enable wifi-mesh-control
systemctl enable femto-wifi-mesh-control
systemctl enable femto-watchclock-dog
systemctl disable ttyd # enabled on first boot
systemctl disable meshtasticd # enabled on first boot
systemctl disable apt-daily.timer
systemctl disable apt-daily-upgrade.timer
systemctl mask apt-daily.service # try prevent daily updates
systemctl mask apt-daily-upgrade.service # try prevent daily updates
systemctl disable unattended-upgrades
systemctl disable smbd nmbd # samba services, can be enabled via menu
systemctl disable NetworkManager
@ -98,6 +111,20 @@ sudo chage -d 0 femto
usermod -a -G tty femto
usermod -a -G dialout femto
# Ensure libgcc_s.so and libc_nonshared.a exist
mkdir -p /usr/lib/gcc/arm-linux-gnueabihf/11/
ln -sf /usr/lib/arm-linux-gnueabihf/libgcc_s.so.1 /usr/lib/gcc/arm-linux-gnueabihf/11/libgcc_s.so
ln -sf /usr/lib/arm-linux-gnueabihf/libgcc_s.so.1 /lib/libgcc_s.so.1
ln -sf /usr/lib/gcc/arm-linux-gnueabihf/11/libgcc_s.so /usr/lib/libgcc.so
# Add library paths
echo "/usr/lib/gcc/arm-linux-gnueabihf/11" | tee -a /etc/ld.so.conf.d/gcc.conf
ldconfig
# Back up libc_nonshared.a because build.sh removes it
cp /usr/lib/arm-linux-gnueabihf/libc_nonshared.a /usr/lib/arm-linux-gnueabihf/libc_nonshared.a.keep
echo "Cleaning up chroot..."
apt clean && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* && rm -rf /var/tmp/* && find /var/log -type f -exec truncate -s 0 {} + && : > /root/.bash_history && history -c
rm -rf /tmp/* && rm -rf /var/tmp/* && find /var/log -type f -exec truncate -s 0 {} + && : > /root/.bash_history && history -c
exit

View file

@ -12,15 +12,11 @@ if [[ $(id -u) != 0 ]]; then
exit 1
fi
if [ -f /etc/os-release ]; then
. /etc/os-release
if [ "$VERSION_ID" != "22.04" ] || [ "$NAME" != "Ubuntu" ]; then
echo "This script is intended for Ubuntu 22.04, exiting..."
exit 1
fi
else
echo "This script is intended for Ubuntu 22.04, exiting..."
exit 1
[ -f /etc/os-release ] && . /etc/os-release
if [ "$VERSION_ID" != "22.04" ] || [ "$NAME" != "Ubuntu" ]; then
echo -e "This script is intended for Ubuntu 22.04, your operating system is not supported (but may work).\nPress Ctrl+C to cancel, or Enter to continue."
read
fi
sudoer=$(echo $SUDO_USER)
@ -61,7 +57,8 @@ clone_repos() {
fi
}
clone_with_retries "https://github.com/LuckfoxTECH/luckfox-pico.git" || return 1
#clone_with_retries "https://github.com/LuckfoxTECH/luckfox-pico.git" || return 1
clone_with_retries "https://github.com/Ruledo/luckfox-pico.git" || return 1
clone_with_retries "https://github.com/femtofox/femtofox.git" || return 1
return 0

View file

@ -1,2 +1 @@
first_boot=true
act_led=enable

View file

@ -1,5 +1,5 @@
major=0
minor=99
major=1
minor=0
patch=0
hotfix=

View file

@ -0,0 +1,11 @@
# this sets the mac address source to eth0, replacing the previous code that derived a seed from the CPU s/n.
# of course, eth0 also has its mac address derived from CPU s/n, but this way meshtastic uses the exact mac address, instead of a bastardized version converted to a 9 digit int with `| bc | tail -c -9`.
General:
MACAddressSource: eth0
# this activates the webserver
Webserver:
Port: 443 # Port for Webserver & Webservices
RootPath: /usr/share/meshtasticd/web # Root Dir of WebServer
SSLKey: /etc/meshtasticd/ssl/private_key.pem # Path to SSL Key, generated if>
SSLCert: /etc/meshtasticd/ssl/certificate.pem # Pa

View file

@ -8,4 +8,13 @@ iface lo inet loopback
allow-hotplug wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
metric 100
post-up sleep 5 && dhclient wlan0
pre-down ip route del default via $(ip route | awk '/default/ {print $3}') dev wlan0 metric 100
allow-hotplug eth0
iface eth0 inet dhcp
metric 10
post-up ip route replace default via $(ip route | awk '/default/ {print $3}') dev eth0 metric 10
pre-down ip route del default via $(ip route | awk '/default/ {print $3}') dev eth0 metric 10

View file

@ -1,7 +1,7 @@
[Unit]
Description=Boot Complete
After=serial-getty@ttyFIQ0.service
DefaultDependencies=no
After=multi-user.target femto-usb-config-tool.service
[Service]
ExecStart=/usr/local/bin/femto-boot-complete.sh
@ -11,4 +11,4 @@ StandardOutput=journal+console
StandardError=journal+console
[Install]
WantedBy=default.target
WantedBy=default.target

View file

@ -1,6 +1,6 @@
[Unit]
Description=Foxbuntu First Boot
After=meshtasticd.service
After=rc-local.service
Before=serial-getty@ttyFIQ0.service
DefaultDependencies=no

View file

@ -1,6 +1,6 @@
[Unit]
Description=Foxbuntu USB Configuration Tool
After=meshtasticd.service
After=rc-local.service
Before=serial-getty@ttyFIQ0.service
DefaultDependencies=no

View file

@ -0,0 +1,12 @@
[Unit]
Description=Watchclock-dog
After=network.target
[Service]
ExecStart=/usr/local/bin/femto-watchclock-dog.sh
Restart=always
User=root
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,12 @@
[Unit]
Description=Sync wifi updown with Meshtastic
After=meshtasticd.service
[Service]
ExecStart=/usr/local/bin/femto-wifi-mesh-control.sh
Restart=always
RestartSec=5
User=root
[Install]
WantedBy=multi-user.target

View file

@ -1,6 +1,4 @@
[Service]
ExecStart=
ExecStart=/bin/sh -c '/usr/sbin/meshtasticd -h $(sed -n "/Serial/ s/^.*: \(.*\)$/\U\1/p" /proc/cpuinfo | bc | tail -c 9)'
Nice=-20
[Unit]

View file

@ -0,0 +1,7 @@
[Unit]
After=femto-boot-complete.service multi-user.target
Conflicts=getty.target
Before=getty.target
[Service]
ExecStartPre=/bin/sleep 0.5

View file

@ -12,11 +12,11 @@ if [ -z "$DISTRIB_DESCRIPTION" ] && [ -x /usr/bin/lsb_release ]; then
fi
[ -r /etc/lsb-release ] && . /etc/lsb-release
foxbuntu_version=$(grep -oP 'major=\K[0-9]+' /etc/foxbuntu-release).$(grep -oP 'minor=\K[0-9]+' /etc/foxbuntu-release)$(output=$(grep -o 'patch=[1-9][0-9]*' /etc/foxbuntu-release | cut -d= -f2) && [ -n "$output" ] && echo ".$output")$(grep -oP 'hotfix=\K[a-z]+' /etc/foxbuntu-release)
spaces=$((11 - ${#foxbuntu_version}))
foxbuntu_version=$(femto-utils.sh -v)
spaces=$((21 - ${#foxbuntu_version}))
printf " For settings, run \`\033[0;31msudo femto-config\033[0m\`\n"
printf " Made for Femtofox https://www.femtofox.com\n"
printf " Foxbuntu v$foxbuntu_version%*s%s(%s)\n\n" $spaces "" "$DISTRIB_DESCRIPTION" "$(uname -r)"
printf " $foxbuntu_version%*s%s(%s)\n\n" $spaces "" "$DISTRIB_DESCRIPTION" "$(uname -r)"
printf "IP address: $(hostname -I | sed 's/ / /g') Uptime:$(uptime -p | awk '{$1=""; print $0}' | sed -e 's/ day\b/d/g' -e 's/ hour\b/h/g' -e 's/ hours\b/h/g' -e 's/ minute\b/m/g' -e 's/ minutes\b/m/g' | sed 's/,//g')\n"

View file

@ -1,11 +0,0 @@
[Unit]
Description=Run settime script at startup
Before=meshtasticd.service
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/settime.sh
[Install]
WantedBy=default.target

View file

@ -1,12 +0,0 @@
[Unit]
Description=Meshtastic control of wifi
After=meshtasticd.service
Requires=meshtasticd.service
[Service]
ExecStart=/usr/local/bin/wifi-mesh-control.sh
Restart=always
User=root
[Install]
WantedBy=multi-user.target

View file

@ -27,4 +27,10 @@ form_text_color = (WHITE,CYAN,ON)
form_item_readonly_color = (BLUE,WHITE,ON)
# Item help-text color
itemhelp_color = (BLACK,BLUE,OFF)
itemhelp_color = (WHITE,BLUE,OFF)
# Selected tag color (menu items)
tag_selected_color = (WHITE,BLUE,ON)
# Tag color (menu items)
tag_color = (BLACK,WHITE,OFF)

View file

@ -1,6 +1,6 @@
#!/bin/bash
if grep -qE '^first_boot=true' /etc/femto.conf; then
log_message "First boot, skipping \`boot complete\` tasks."
echo "First boot, skipping \`boot complete\` tasks."
exit 0
fi

View file

@ -16,29 +16,12 @@ pause() {
read -n 1 -s -r
}
# Dialog uses a different method to display colors, and is limited to only these 8.
replace_colors() {
input="$1"
input="${input//$(echo -e '\033[0;30m')/\\Z0}" # black
input="${input//$(echo -e '\033[0;31m')/\\Z1}" # red
input="${input//$(echo -e '\033[0;32m')/\\Z2}" # green
input="${input//$(echo -e '\033[0;33m')/\\Z3}" # yellow
input="${input//$(echo -e '\033[0;34m')/\\Z4}" # blue
input="${input//$(echo -e '\033[0;35m')/\\Z5}" # magenta
input="${input//$(echo -e '\033[0;36m')/\\Z6}" # cyan
input="${input//$(echo -e '\033[0;37m')/\\Z7}" # white
input="${input//$(echo -e '\033[7m')/\\Zr}" # invert
input="${input//$(echo -e '\033[4m')/\\Zu}" # underline
input="${input//$(echo -e '\033[0m')/\\Zn}" # reset
echo "$input"
}
loading() {
dialog --no-collapse --infobox "$1" 5 45
}
## function to pull data from various femto scripts and convert it to the contents of a read only dialog --form
# ingest_data() { # usage: `ingest_data "command.sh -argument" key_width value_width`
# ingest_form_data() { # usage: `ingest_form_data "command.sh -argument" key_width value_width`
# unset output_array #debug code, delete me
# declare -a output_array
# # Read the output from femto-meshtasticd-config.sh and store it in the array
@ -59,7 +42,7 @@ loading() {
# echo "$form_contents" | sed 's/\x1b\[[0-9;]*m//g'
# }
## CODE TO USE THIS FUNCTION:
# eval "$(echo -e "dialog --no-collapse --no-cancel --form \"Meshtastic node info\" 0 0 0 $(ingest_data "femto-meshtasticd-config.sh -i" 18 0) 2>/dev/null")"
# eval "$(echo -e "dialog --no-collapse --no-cancel --form \"Meshtastic node info\" 0 0 0 $(ingest_form_data "femto-meshtasticd-config.sh -i" 18 0) 2>/dev/null")"
# function to pull data from various femto scripts and convert it a simple text string, with dialog colors
@ -67,9 +50,8 @@ ingest_data() { # usage: `ingest_data "command.sh -argument" key_width`
local output_string=""
# Read the output from femto-meshtasticd-config.sh and store output_string
while IFS=':' read -r key value; do
# Trim leading/trailing spaces from key and value
key=$(replace_colors "$(echo "$key" | xargs)")
value=$(replace_colors "$(echo "$value" | xargs)")
key=$(femto-utils.sh -R "$(echo "$key")")
value=$(femto-utils.sh -R "$(echo "$value" | xargs)") # Trim leading/trailing spaces from value
if [[ -z "$key" && -z "$value" ]]; then
output_string+="---\n"
else
@ -79,6 +61,89 @@ ingest_data() { # usage: `ingest_data "command.sh -argument" key_width`
echo -e "$output_string"
}
check_meshtasticd_running() {
if ! echo $(femto-utils.sh -C "meshtasticd") | sed 's/\x1b\[[0-9;]*m//g' | grep -q ", running"; then
dialog --no-collapse --title "Meshtasticd service" --yesno "Meshtasticd service is not running but is required.\n\nStart service?" 9 50
if [ $? -eq 0 ]; then #unless cancel/no
femto-meshtasticd-config.sh -s
echo "Waiting for meshtasticd service to start..."
sleep 3
if ! echo $(femto-utils.sh -C "meshtasticd") | sed 's/\x1b\[[0-9;]*m//g' | grep -q ", running"; then
dialog --no-collapse --colors --title "Meshtasticd service" --msgbox "Meshtasticd service ($(femto-utils.sh -R "$(femto-utils.sh -C "meshtasticd")")) failed to run, but is required." 7 50
return 1
fi
return 0
else
return 1
fi
fi
}
service_manager() {
choice="" # zero the choice before loading the submenu
while true; do
local service_name=$1
local readable_name=$2
local help=$3
echo "Checking $readable_name service state..."
local service_state="$(femto-utils.sh -R "$(femto-utils.sh -C "$service_name")")"
choice=$(dialog --no-collapse --colors --help-button --cancel-label "Back" --title "$readable_name Service" --default-item "$choice" --menu "Avahi-Daemon service is $service_state" 16 60 5 \
"View detailed service status" "x" \
" " "" \
"Start/restart service" "x" \
$(if ! echo "$service_state" | grep -q 'not running'; then echo "Stop service x"; fi) \
" " "" \
$(if echo "$service_state" | grep -q 'disabled'; then echo "Enable service x"; fi) \
$(if echo "$service_state" | grep -q 'enabled'; then echo "Disable service x"; fi) \
" " "" \
"Back to previous menu" "x" 3>&1 1>&2 2>&3)
exit_status=$? # This line checks the exit status of the dialog command
if [ $exit_status -eq 1 ]; then # Exit the loop if the user selects "Cancel" or closes the dialog
break
elif [ $exit_status -eq 2 ]; then # Help ("extra") button
dialog --no-collapse --colors --title "$readable_name service help" --msgbox "$3" 0 0
else
case $choice in
"View detailed service status")
echo "Getting $readable_name service status..."
dialog --no-collapse --title "$readable_name service status" --msgbox "$(systemctl status $service_name)" 0 0
;;
"Start/restart service")
dialog --no-collapse --title "$title" --yesno "Start/restart $readable_name service?" 7 45
if [ $? -eq 0 ]; then #unless cancel/no
systemctl restart $service_name
dialog --no-collapse --colors --msgbox "Sent \`\Zusystemctl restart $service_name\Zn\` command to system.\n\n$readable_name should be running." 10 60
fi
;;
"Stop service")
dialog --no-collapse --colors --title "$title" --yesno "Stop $readable_name service?\n\nThis will take the node \Zu\Z1OFFLINE\Zn.\n\n$readable_name will automatically restart on boot service if enabled." 11 50
if [ $? -eq 0 ]; then #unless cancel/no
systemctl stop $service_name
dialog --no-collapse --colors --msgbox "Sent \`\Zusystemctl stop $service_name\Zn\` command to system.\n\n$readable_name should be stopped." 9 60
fi
;;
"Enable service")
dialog --no-collapse --title "$title" --yesno "Enable $readable_name service?" 6 45
if [ $? -eq 0 ]; then #unless cancel/no
systemctl enable $service_name
systemctl start $service_name
dialog --no-collapse --colors --msgbox "Sent \`\Zusystemctl enable $service_name\Zn\` and \`\Zusystemctl start $service_name\Zn\` commands to system.\n\n$readable_name should be running." 10 60
fi
;;
"Disable service")
dialog --no-collapse --colors --title "$title" --yesno "Disable $readable_name service?\n\nThis will take the node \Zu\Z1OFFLINE\Zn and will not restart!" 9 50
if [ $? -eq 0 ]; then #unless cancel/no
systemctl disable $service_name
systemctl stop $service_name
dialog --no-collapse --colors --msgbox "Sent \`\Zusystemctl disable $service_name\Zn\` and \`\Zusystemctl stop $service_name\Zn\` commands to system.\n\n$readable_name should be disabled and stopped." 10 60
fi
;;
"Back to previous menu") break ;;
esac
fi
done
}
wifi_config() {
local title2="Wi-Fi (wlan0) Settings"
local config=$(dialog --no-collapse --title "$title2" --form "↑ ↓ to navigate, [ESC] to cancel." 10 45 0 \
@ -113,7 +178,7 @@ networking_settings() {
wpa_supplicant_conf="/etc/wpa_supplicant/wpa_supplicant.conf"
choice="" # zero the choice before loading the submenu
while true; do
networking_choice=$(dialog --no-collapse --cancel-label "Back" --backtitle "IPv4 address: $(femto-network-config.sh -i)" --default-item "$networking_choice" --title "$title" --item-help --menu "" 16 40 4 \
networking_choice=$(dialog --no-collapse --cancel-label "Back" --backtitle "IPv4 address: $(femto-network-config.sh -i)" --default-item "$networking_choice" --title "$title" --item-help --menu "" 17 40 4 \
1 "Turn Wi-Fi on/off" "" \
2 "View Wi-Fi settings" "" \
3 "Change Wi-Fi settings" "" \
@ -121,8 +186,10 @@ networking_settings() {
5 "Restart networking" "" \
6 "Set hostname" "" \
7 "Test internet connection" "" \
8 "Manage Meshtastic wifi sync" "" \
9 "Manage Avahi-Daemon service" "" \
" " "" "" \
8 "Back to main menu" "" 3>&1 1>&2 2>&3)
10 "Back to main menu" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $networking_choice in
1) # Turn Wi-Fi on/off)
@ -170,9 +237,15 @@ networking_settings() {
;;
7) # Test internet connection)
loading "Testing internet connection..."
dialog --no-collapse --title "Internet connectivity test" --colors --msgbox "$(replace_colors "$(femto-network-config.sh -t)")" 8 40
dialog --no-collapse --title "Internet connectivity test" --colors --msgbox "$(femto-utils.sh -R "$(femto-network-config.sh -t)")" 9 40
;;
8)
8) # Manage Meshtastic wifi sync)
service_manager "femto-wifi-mesh-control" "Meshtastic wifi sync" "The Meshtastic wifi sync service synchronizes system wifi settings with Meshtastic wifi settings. This allows you to use Meshtastic's remote node administration feature to enable/disable wifi.\n\nIn future, this will also allow you to reconfigure SSID and password.\n"
;;
9) # Manage avahi)
service_manager "avahi-daemon" "Avahi Daemon" "The Avahi-Daemon service advertises the Meshtastic node on the local LAN (often called a Bonjour service), allowing the Android app to detect it. Without Avahi, you will need to manually enter the Femtofox's IP address in the app to connect.\n"
;;
10)
return
;;
esac
@ -186,18 +259,17 @@ utilities() {
utilities_choice=$(dialog --no-collapse --cancel-label "Back" --default-item "$utilities_choice" --item-help --menu "$title" 21 50 4 \
1 "View system info" "" \
2 "Set system time" "" \
3 "Kernel modules" "" \
3 "Kernel module manager" "" \
4 "Re-run first-boot script" "" \
5 "Run USB configuration tool" "" \
6 "Run OEM luckfox-config" "" \
7 "Process viewer/manager" "" \
8 "Disable/enable web terminal" "" \
9 "Disable/enable logging" "" \
10 "Disable/enable activity LED" "" \
11 "Reboot" "" \
12 "Shutdown" "" \
8 "Disable/enable logging" "" \
9 "Disable/enable activity LED" "" \
10 "Reboot" "" \
11 "Shutdown" "" \
" " "" "" \
13 "Back to main menu" "" 3>&1 1>&2 2>&3)
12 "Back to main menu" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $utilities_choice in
@ -205,9 +277,9 @@ utilities() {
sysinfo_choice="" # zero the choice before loading the submenu
while true; do
echo $sysinfo_choice
sysinfo_choice=$(dialog --no-collapse --help-button --cancel-label "Back" --default-item "$sysinfo_choice" --item-help --menu "System info" 17 40 5 \
1 "CPU" "" \
2 "Operating system" "" \
sysinfo_choice=$(dialog --no-collapse --help-button --backtitle "$(femto-utils.sh -v)" --cancel-label "Back" --default-item "$sysinfo_choice" --item-help --menu "System info" 17 40 5 \
1 "Operating system" "" \
2 "CPU" "" \
3 "Storage & memory" "" \
4 "Peripherals & devices" ""\
5 "Networking" "" \
@ -219,17 +291,17 @@ utilities() {
if [ $exit_status -eq 1 ]; then # Exit the loop if the user selects "Cancel" or closes the dialog
break
elif [ $exit_status -eq 2 ]; then # Help ("extra") button
dialog --no-collapse --colors --title "System info help" --msgbox "To get system info in terminal (where it can be copied), enter \`\Zusudo femto-utils.sh -i\Zn\`.\n\nWhen getting Peripherals & Devices (or Complete System Info) without an i2c device connected, it is normal to see error messages on serial console.\n" 0 0
dialog --no-collapse --colors --title "System info help" --msgbox "To get system info in terminal (where it can be copied), enter \`\Zusudo femto-utils.sh -i\Zn\`.\n\nWhen getting Peripherals & Devices Info (or Complete System Info) without an i2c device connected, it is normal to see error messages on serial console.\n" 0 0
else
case $sysinfo_choice in
1) # CPU)
loading "Loading CPU info..."
dialog --no-collapse --colors --title "CPU info" --msgbox "$(ingest_data "femto-utils.sh -c" 15)" 0 0
;;
2) # Operating system)
1) # Operating system)
loading "Loading operating system info..."
dialog --no-collapse --colors --title "Operating system info" --msgbox "$(ingest_data "femto-utils.sh -o" 15)" 0 0
;;
2) # CPU)
loading "Loading CPU info..."
dialog --no-collapse --colors --title "CPU info" --msgbox "$(ingest_data "femto-utils.sh -c" 15)" 0 0
;;
3) # Storage & memory)
loading "Loading storage & memory info..."
dialog --no-collapse --colors --title "Storage & memory info" --msgbox "$(ingest_data "femto-utils.sh -S" 15)" 0 0
@ -243,30 +315,14 @@ utilities() {
dialog --no-collapse --colors --title "Networking info" --msgbox "$(ingest_data "femto-utils.sh -n" 15)" 0 0
;;
6) # Meshtastic node info)
loading "Loading Meshtastic node info..."
dialog --no-collapse --colors --title "Meshtastic node info" --msgbox "$(ingest_data "femto-meshtasticd-config.sh -i" 15)" 0 0
check_meshtasticd_running && (
loading "Loading Meshtastic node info..."
dialog --no-collapse --colors --title "Meshtastic node info" --msgbox "$(ingest_data "femto-meshtasticd-config.sh -i" 15)" 0 0
)
;;
7) # Complete system info)
loading "Loading complete system info..."
dialog --no-collapse --colors --title "Meshtastic node info" --msgbox "\
Femtofox
CPU:
$(ingest_data "femto-utils.sh -c" 15)
Operating System:
$(ingest_data "femto-utils.sh -o" 15)
Storage:
$(ingest_data "femto-utils.sh -S" 15)
Networking (wlan0 & eth0):
$(ingest_data "femto-utils.sh -p" 15)
Peripherals:
$(ingest_data "femto-utils.sh -n" 15)
Meshtasticd:
$(ingest_data "femto-meshtasticd-config.sh -i" 15)" 0 0
dialog --no-collapse --colors --title "Complete system info" --msgbox "$(ingest_data "femto-utils.sh -i" 15)" 0 0
;;
8) break ;;
esac
@ -275,7 +331,6 @@ $(ingest_data "femto-meshtasticd-config.sh -i" 15)" 0 0
;;
2) femto-set-time.sh ;; # set timezone
3) # Kernel modules)
dialog --no-collapse --title "$title" --msgbox "Kernel modules are loadable pieces of code that extend a Linux kernel's functionality without requiring a reboot. Common examples include device drivers, file systems, or system calls.\n\nThis tool will allow you to add pre-compiled modules to the Foxbuntu kernel.\n\nModules currently autostarting at boot: $(modules=$(sed -n '6,$p' /etc/modules | sed ':a;N;$!ba;s/\n/, /g;s/, $//'); [ -z "$modules" ] && echo "none" || echo "$modules")\n\nCurrently active modules: $(lsmod | awk 'NR>1 {print $1}' | tr '\n' ' ')" 18 65
femto-kernel-modules.sh
;;
4) femto-runonce.sh ;; # Re-run first-boot script
@ -288,40 +343,11 @@ $(ingest_data "femto-meshtasticd-config.sh -i" 15)" 0 0
;;
6) luckfox-config ;;
7) htop ;;
8)
choice="" # zero the choice before loading the submenu
while true; do
echo "Checking web terminal status..."
ttyd_state=$(replace_colors "$(femto-utils.sh -t "check")")
[[ $ttyd_state == *"running"* ]] && ttyd_state+="\nWeb terminal available at \Zuhttps://$(hostname).local:7681\Zn"
choice=$(dialog --no-collapse --colors --title "Web Terminal" --cancel-label "Back" --help-button --default-item "$choice" --item-help --menu "Current state: $ttyd_state" 14 58 2 \
$(if ! echo "$ttyd_state" | grep -q 'enabled and running'; then echo "Enable and start (default) x  "; fi) \
$(if echo "$ttyd_state" | grep -q 'enabled'; then echo "Disable and stop x  "; fi) \
$(if echo "$ttyd_state" | grep -q 'enabled'; then echo "Start/restart ttyd service x  "; fi) \
$(if echo "$ttyd_state" | grep -q 'enabled'; then echo "View detailed service status x  "; fi) \
" " "" "" \
"Return to previous menu" "x" "" 3>&1 1>&2 2>&3)
exit_status=$? # This line checks the exit status of the dialog command
if [ $exit_status -eq 1 ]; then # Exit the loop if the user selects "Cancel" or closes the dialog
break
elif [ $exit_status -eq 2 ]; then # Help ("extra") button
dialog --no-collapse --colors --title "Web terminal help" --msgbox "Web terminal is a browser based terminal interface, and can be used as a replacement for an SSH client such as PuTTY.\nSSL encryption is provided by keys generated during first-boot. Your browser may give a warning (net::ERR_CERT_AUTHORITY_INVALID) about the self-signed encryption certificate. This is normal. In Chromium (Chrome, Edge) click \"Advanced\" and \"Continue to femtofox.local (unsafe)\".\n\nWeb terminal is provided by ttyd.\nLicense for ttyd: \`cat /opt/ttyd/license\`.\nFor more details, see: \Zuhttps://github.com/tsl0922/ttyd\Zn\n\nWeb terminal is enabled by default on Foxbuntu." 0 0
else
case $choice in
"Enable and start (default)") femto-utils.sh -t "enable" ;;
"Disable and stop") femto-utils.sh -t "disable" ;;
"Start/restart ttyd service") femto-utils.sh -t "start" ;;
"View detailed service status") dialog --no-collapse --title "ttyd service status" --msgbox "$(systemctl status ttyd)" 0 0 ;;
"Return to previous menu") break ;;
esac
fi
done
;;
9) # logging)
8) # logging)
choice="" # zero the choice before loading the submenu
while true; do
echo "Checking current logging status..."
choice=$(dialog --no-collapse --colors --title "Logging" --cancel-label "Back" --default-item "$choice" --item-help --menu "Before deploying a Femtofox, it is advisable to disable logging to reduce SD card wear.\nCurrent state: $(replace_colors "$(femto-utils.sh -l "check")")" 14 50 2 \
choice=$(dialog --no-collapse --colors --title "Logging" --cancel-label "Back" --default-item "$choice" --item-help --menu "Before deploying a Femtofox, it is advisable to disable logging to reduce SD card wear.\nCurrent state: $(femto-utils.sh -R "$(femto-utils.sh -l "check")")" 14 50 2 \
1 "Enable (default)" "" \
2 "Disable" "" \
" " "" "" \
@ -334,11 +360,11 @@ $(ingest_data "femto-meshtasticd-config.sh -i" 15)" 0 0
esac
done
;;
10) # activity LED)
9) # activity LED)
choice="" # zero the choice before loading the submenu
while true; do
echo "Checking current activity LED status..."
choice=$(dialog --no-collapse --colors --title "Logging" --cancel-label "Back" --default-item "$choice" --item-help --menu "Before deploying a Femtofox, it is advisable to disable the Activity LED to save power.\nCurrent state: $(replace_colors "$(femto-utils.sh -a "check")")" 14 50 2 \
choice=$(dialog --no-collapse --colors --title "Logging" --cancel-label "Back" --default-item "$choice" --item-help --menu "Before deploying a Femtofox, it is advisable to disable the Activity LED to save power.\nCurrent state: $(femto-utils.sh -R "$(femto-utils.sh -a "check")")" 14 50 2 \
1 "Enable (default)" "" \
2 "Disable" "" \
" " "" "" \
@ -351,42 +377,87 @@ $(ingest_data "femto-meshtasticd-config.sh -i" 15)" 0 0
esac
done
;;
11) # reboot)
10) # reboot)
dialog --no-collapse --title "$title" --yesno "Reboot now?\n\nTip: Reboot can also be triggered by long-pressing the BOOT button on the luckfox." 10 45
if [ $? -eq 0 ]; then #unless cancel/no
loading "Rebooting..."
femto-utils.sh -r
fi
;;
12) # shutdown)
11) # shutdown)
dialog --no-collapse --colors --title "$title" --yesno "Shut down now?\n\nTo power system back on, disconnect/reconnect power.\n\nThe system shutdown command prevents damage to the filesystem from power interrupts, but does not stop power consumption.\n\nTip: You can also shut down the Femtofox by pressing the BOOT button for 5 seconds or by running \`\Zusudo halt\Zn\`." 14 60
if [ $? -eq 0 ]; then #unless cancel/no
loading "Shutting down...\n\nPower consumption will not stop."
femto-utils.sh -s
fi
;;
13) return ;;
12) return ;;
esac
done
}
#set lora radio
legacy_admin() {
choice="" # zero the choice before loading the submenu
while true; do
loading "Getting current legacy admin state..."
choice=$(dialog --no-collapse --colors --title "Legacy Admin" --default-item "$choice" --help-button --item-help --menu "If the node you Femtofox needs to administer or be administered by is running 2.4.x or earlier, you should set this to Enabled.\n\nCurrent state: $(femto-utils.sh -R "$(femto-meshtasticd-config.sh -p)")" 16 65 5 \
1 "Enable" "" \
2 "Disable (default)" "" \
" " "" "" \
3 "Return to previous menu" "" 3>&1 1>&2 2>&3)
exit_status=$? # This line checks the exit status of the dialog command
if [ $exit_status -eq 1 ]; then # Exit the loop if the user selects "Cancel" or closes the dialog
break
elif [ $exit_status -eq 2 ]; then # Help ("extra") button
dialog --no-collapse --colors --title "System info help" --msgbox "For Meshtastic versions 2.4.x and earlier, remote admin is achieved by creating a secondary channel named admin with a shared PSK. In this setup, messages exchanged on this channel are encrypted only with the channel's PSK, allowing any node in the channel to administer others.\n\nFor more information:\nhttps://meshtastic.org/docs/configuration/remote-admin/\n" 0 0
else
case $choice in
1) # enable legacy admin)
dialog --no-collapse --title "Legacy Admin" --yesno "Enable legacy admin channel?\n" 0 0
if [ $? -eq 0 ]; then #unless cancel/no
loading "Sending command..."
dialog --no-collapse --colors --title "Legacy admin" --msgbox "$(femto-meshtasticd-config.sh -o "true" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
;;
2) # disable legacy admin)
dialog --no-collapse --title "Legacy Admin" --yesno "Disable legacy admin channel?\n" 0 0
if [ $? -eq 0 ]; then #unless cancel/no
loading "Sending command..."
dialog --no-collapse --colors --title "Legacy admin" --msgbox "$(femto-meshtasticd-config.sh -o "false" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
;;
3) break ;;
esac
fi
done
}
meshtastic_config_url() {
newurl=$(dialog --no-collapse --colors --title "Meshtastic URL" --inputbox "The Meshtastic configuration URL allows for automatic configuration of all Meshtastic LoRa settings and channels.\n\nEntering a URL may \Z1\ZuOVERWRITE\Zn your LoRa settings and channels!\n\nNew Meshtastic LoRa configuration URL (SHIFT+INS to paste):" 14 63 3>&1 1>&2 2>&3)
if [ -n "$newurl" ]; then #if a URL was entered
femto-meshtasticd-config.sh -q "$newurl"
fi
}
set_lora_radio() {
choice="" # zero the choice before loading the submenu
while true; do
echo "Checking LoRa radio..."
#Display filename, if exists: $(files=$(ls /etc/meshtasticd/config.d/* 2>/dev/null) && [ -n "$files" ] && echo "\n\nConfiguration files in use:\n$files" | paste -sd, -))
choice=$(dialog --no-collapse --colors --cancel-label "Cancel" --default-item "$choice" --title "Meshtastic LoRa radio" --item-help --menu "Currently configured LoRa radio:\n$(replace_colors "$(femto-meshtasticd-config.sh -k)")$(ls -1 /etc/meshtasticd/config.d 2>/dev/null | paste -sd ', ' - | sed 's/^/ (/; s/$/)/; s/,/, /g' | grep -v '^ ()$')" 19 50 10 \
"Ebyte e22-900m30s" "(SX1262_TCXO)" "" \
"Ebyte e22-900m22s" "(SX1262_TCXO)" "" \
"Ebyte e80-900m22s" "(SX1262_XTAL)" "" \
"Heltec ht-ra62" "(SX1262_TCXO)" "" \
"Seeed wio-sx1262" "(SX1262_TCXO)" "" \
"Waveshare sx126x-xxxm" "(SX1262_XTAL)" "" \
"AI Thinker ra-01sh" "(SX1262_XTAL)" "" \
"None" "(simulated radio)" "" \
choice=$(dialog --no-collapse --colors --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --default-item "$choice" --title "Meshtastic LoRa radio" --item-help --menu "Currently configured LoRa radio:\n$(femto-utils.sh -R "$(femto-meshtasticd-config.sh -k)")$(ls -1 /etc/meshtasticd/config.d 2>/dev/null | grep -v '^femto_' | paste -sd ', ' - | sed 's/^/ (/; s/$/)/; s/,/, /g' | grep -v '^ ()$')" 22 50 10 \
"Radio name:" "Configuration:" "" \
"" "" "" \
"Ebyte e22-900m30s" "(SX1262_TCXO)" "Included in Femtofox Pro" \
"Ebyte e22-900m22s" "(SX1262_TCXO)" "" \
"Ebyte e80-900m22s" "(SX1262_XTAL)" "" \
"Heltec ht-ra62" "(SX1262_TCXO)" "" \
"Seeed wio-sx1262" "(SX1262_TCXO)" "" \
"Waveshare sx126x-xxxm" "(SX1262_XTAL)" "Not recommended due issues with sending longer messages" \
"AI Thinker ra-01sh" "(SX1262_XTAL)" "" \
"LoRa Meshstick 1262" "(meshstick-1262)" "USB based LoRa radio from Mark Birss. https://github.com/markbirss/MESHSTICK" \
"Simulated radio" "(none)" "" \
" " "" "" \
"Skip" "" "" 3>&1 1>&2 2>&3)
"Cancel" "" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
local radio=""
case $choice in
@ -409,18 +480,22 @@ set_lora_radio() {
radio="sx1262_xtal"
;;
"AI Thinker ra-01sh")
radio="sx1262_xtal"
radio="femto_sx1262_xtal"
;;
"None")
"LoRa Meshstick 1262")
radio="lora-meshstick-1262"
;;
"Simulated radio")
radio="none"
;;
"Skip")
"Cancel")
return
;;
esac
if [ -n "$radio" ]; then #if a radio was selected
femto-meshtasticd-config.sh -l "$radio" -s # set the radio, then restart meshtasticd
return
dialog --no-collapse --colors --title "$title" --msgbox "$(echo -e "Radio \Zu$choice\Zn selected.\nMeshtasticd service restarted.\Zn")" 7 45
break
fi
done
}
@ -430,182 +505,93 @@ meshtastic_settings() {
local title="Meshtastic Settings"
while true; do
echo "Checking Meshtasticd service state..."
meshtastic_choice=$(dialog --no-collapse --colors --title "$title" --cancel-label "Back" --default-item "$meshtastic_choice" --item-help --menu "Meshtasticd service is $(replace_colors "$(femto-meshtasticd-config.sh -S)")$(femto-meshtasticd-config.sh -k | grep -q 'simulated' && echo '\n\Z1Warning: using simulated radio\Zn')" 20 50 4 \
meshtastic_choice=$(dialog --no-collapse --colors --title "$title" --cancel-label "Back" --default-item "$meshtastic_choice" --item-help --menu "Meshtasticd service is $(femto-utils.sh -R "$(femto-utils.sh -C "meshtasticd")")$(femto-meshtasticd-config.sh -k | grep -q 'simulated' && echo '\n\Z1Warning: using simulated radio\Zn')" 20 50 4 \
1 "View node info" "" \
2 "View configuration URL & QR code" "" \
3 "Set new configuration URL" "" \
4 "Set LoRa radio" "" \
5 "Security settings" "" \
2 "Set LoRa radio model" "" \
3 "View configuration URL & QR code" "" \
4 "Set configuration URL" "" \
5 "Full Meshtastic settings" "" \
6 "Mesh connectivity test" "" \
7 "Manage Meshtasticd service" "" \
8 "Upgrade/install Meshtasticd" "" \
9 "Uninstall Meshtasticd" "" \
8 "Enable/disable i2c support" "" \
9 "Upgrade/install Meshtasticd" "" \
10 "Uninstall Meshtasticd" "" \
" " "" "" \
10 "Back to main menu" "" 3>&1 1>&2 2>&3)
11 "Back to main menu" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $meshtastic_choice in
1) # view node info)
loading "Getting node info..."
dialog --no-collapse --colors --title "Meshtastic node info" --msgbox "$(ingest_data "femto-meshtasticd-config.sh -i" 15)" 0 0
;;
2) # get current configuration URL & QR code)
loading "Getting Meshtastic QR code and URL..."
femto-meshtasticd-config.sh -g
pause
check_meshtasticd_running && (
loading "Getting node info..."
dialog --no-collapse --colors --title "Meshtastic node info" --msgbox "$(ingest_data "femto-meshtasticd-config.sh -i" 15)" 0 0
)
;;
3) # set URL)
newurl=$(dialog --no-collapse --title "Meshtastic URL" --inputbox "New Meshtastic LoRa configuration URL (SHIFT+INS to paste):" 8 60 3>&1 1>&2 2>&3)
if [ -n "$newurl" ]; then #if a URL was entered
dialog --no-collapse --title "$title" --yesno "New Meshtastic LoRa configuration URL:\n$newurl\n\nConfirm?" 15 60
if [ $? -eq 0 ]; then #unless cancel/no
loading "Sending command..."
dialog --no-collapse --colors --title "Meshtastic URL" --msgbox "$(femto-meshtasticd-config.sh -q "$newurl" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
fi
;;
4) # set radio)
2) # Set LoRa radio model)
set_lora_radio
;;
5) # remote admin)
choice="" # zero the choice before loading the submenu
while true; do
choice=$(dialog --no-collapse --cancel-label "Back" --default-item "$choice" --title "Meshtastic Security Settings" --item-help --menu "" 16 40 5 \
1 "View/change public key" "" \
2 "View/change private key" "" \
" " "" "" \
3 "View admin keys" "" \
4 "Set admin key" "" \
5 "Clear admin keys" "" \
6 "Legacy admin channel" "" \
" " "" "" \
7 "Return to previous menu" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $choice in
1) # view/change public key)
loading "Getting current public key..."
key=$(femto-meshtasticd-config.sh -u)
if [ -n "$key" ]; then
dialog --no-collapse --title "Meshtastic public key" --yesno "Current public key:\n$key\n\nSet new key?" 9 55
if [ $? -eq 0 ]; then #unless cancel/no
key=$(dialog --no-collapse --title "Meshtastic public key" --inputbox "New Meshtastic public key (SHIFT+INS to paste):" 8 60 3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then #unless cancel/no
loading "Sending command..."
dialog --no-collapse --colors --title "Meshtastic public key" --msgbox "$(femto-meshtasticd-config.sh -U "$key" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
fi
else
dialog --no-collapse --colors --title "Meshtastic public key" --msgbox "\Z1Failed to communicate with Meshtasticd.\Zn\n\nIs the service running?\n" 0 0
fi
;;
2) # view/change private key)
loading "Getting current private key..."
key=$(femto-meshtasticd-config.sh -u)
if [ -n "$key" ]; then
dialog --no-collapse --title "Meshtastic private key" --yesno "Current private key:\n$key\n\nSet new key?" 9 55
if [ $? -eq 0 ]; then #unless cancel/no
key=$(dialog --no-collapse --title "Meshtastic private key" --inputbox "New Meshtastic private key (SHIFT+INS to paste):" 8 60 3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then #unless cancel/no
loading "Sending command..."
dialog --no-collapse --colors --title "Meshtastic private key" --msgbox "$(femto-meshtasticd-config.sh -R "$key" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
fi
else
dialog --no-collapse --colors --title "Meshtastic private key" --msgbox "\Z1Failed to communicate with Meshtasticd.\Zn\n\nIs the service running?\n" 0 0
fi
;;
3) # view admin keys)
loading "Getting Admin Keys..."
dialog --no-collapse --title "Admin keys" --msgbox "Up to 3 admin keys are permitted, more will be ignored.\n\nKeys:$(femto-meshtasticd-config.sh -a | tail -n 1 | sed 's/|n/\\n/g')" 0 0
;;
4) # set admin key)
key=$(dialog --no-collapse --title "Admin Keys" --inputbox "Meshtastic admin key - up to 3, more will be ignored.\n\n(SHIFT+INS to paste):" 11 40 3>&1 1>&2 2>&3)
if [ -n "$key" ]; then #if a key was entered
loading "Sending command..."
dialog --no-collapse --colors --title "Admin Keys" --msgbox "$(femto-meshtasticd-config.sh -A "$key" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
;;
5) # clear admin keys)
dialog --no-collapse --title "Admin Keys" --yesno "Meshtasticd can have up to 3 admin keys. If more are added, they will be ignored.\n\nClear admin key list?\n" 0 0
if [ $? -eq 0 ]; then #unless cancel/no
loading "Sending command..."
dialog --no-collapse --colors --title "Admin Keys" --msgbox "$(femto-meshtasticd-config.sh -c && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
;;
6) # legacy admin)
choice="" # zero the choice before loading the submenu
while true; do
loading "Getting current legacy admin state..."
choice=$(dialog --no-collapse --colors --title "Legacy Admin" --default-item "$choice" --item-help --menu "Current state: $(replace_colors "$(femto-meshtasticd-config.sh -p)")" 12 40 5 \
1 "Enable" "" \
2 "Disable (default)" "" \
" " "" "" \
3 "Return to previous menu" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $choice in
1) # enable legacy admin)
dialog --no-collapse --title "Legacy Admin" --yesno "Enable legacy admin channel?\n" 0 0
if [ $? -eq 0 ]; then #unless cancel/no
loading "Sending command..."
dialog --no-collapse --colors --title "Legacy admin" --msgbox "$(femto-meshtasticd-config.sh -o "true" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
;;
2) # disable legacy admin)
dialog --no-collapse --title "Legacy Admin" --yesno "Disable legacy admin channel?\n" 0 0
if [ $? -eq 0 ]; then #unless cancel/no
loading "Sending command..."
dialog --no-collapse --colors --title "Legacy admin" --msgbox "$(femto-meshtasticd-config.sh -o "false" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
;;
3) break ;;
esac
done
;;
7) # return to previous menu)
break
;;
esac
done
3) # get current configuration URL & QR code)
check_meshtasticd_running && (
loading "Getting Meshtastic QR code and URL..."
femto-meshtasticd-config.sh -g
pause
)
;;
4) # Configure automatically with URL)
check_meshtasticd_running && (
meshtastic_config_url
)
;;
5) # Meshtastic settings)
check_meshtasticd_running && (
dialog --no-collapse --infobox "Loading Meshtastic settings menu...\n\nStopping conflicting services, will restart after exit...\n\nThis can take up to a minute." 9 50
femto-utils.sh -A stop
python /opt/control/main.py --host
echo "Restarting conflicting services..."
femto-utils.sh -A start
)
;;
6) #test mesh connectivity)
dialog --no-collapse --title "Meshtastic Connectivity Test" --yesno "Will send \"test\" to channel 0 and wait for acknowledgement. Will try up to 3 times.\n\nPerform test?" 10 45
if [ $? -eq 0 ]; then #unless cancel/no
dialog --no-collapse --infobox "Performing mesh connectivity test.\n\nThis may take a while..." 6 45
dialog --no-collapse --colors --title "Meshtasticd connectivity test" --msgbox "$(replace_colors "$(femto-meshtasticd-config.sh -w)")" 0 0
fi
check_meshtasticd_running && (
dialog --no-collapse --title "Meshtastic Connectivity Test" --yesno "Will send \"test\" to channel 0 and wait for acknowledgement. Will try up to 3 times.\n\nPerform test?" 10 45
if [ $? -eq 0 ]; then #unless cancel/no
dialog --no-collapse --infobox "Performing mesh connectivity test.\n\nThis may take a while..." 6 45
dialog --no-collapse --colors --title "Meshtasticd connectivity test" --msgbox "$(femto-utils.sh -R "$(femto-meshtasticd-config.sh -w)")" 0 0
fi
)
;;
7) #manage meshtasticd service)
choice="" # zero the choice before loading the submenu
while true; do
echo "Checking Meshtasticd service state..."
local service_state="$(replace_colors "$(femto-meshtasticd-config.sh -S)")"
choice=$(dialog --no-collapse --colors --cancel-label "Back" --title "Meshtasticd Service" --default-item "$choice" --menu "Meshtasticd service is $service_state$(femto-meshtasticd-config.sh -k | grep -q 'simulated' && echo '\n\Z1Using simulated radio\Zn')" 17 52 5 \
local service_state="$(femto-utils.sh -R "$(femto-utils.sh -C "meshtasticd")")"
choice=$(dialog --no-collapse --colors --cancel-label "Back" --title "Meshtasticd Service" --default-item "$choice" --menu "Meshtasticd service is $service_state$(femto-meshtasticd-config.sh -k | grep -q 'simulated' && echo '\n\Z1Using simulated radio\Zn')" 16 52 5 \
"View detailed service status" "x" \
" " " " \
$(if echo "$service_state" | grep -q 'enabled'; then echo "Start/restart service x"; fi) \
$(if echo "$service_state" | grep -q 'enabled and running'; then echo "Stop service x"; fi) \
$(if echo "$service_state" | grep -q 'enabled'; then echo "   "; fi) \
" " "" \
"Start/restart service" "x" \
$(if ! echo "$service_state" | grep -q 'not running'; then echo "Stop service x"; fi) \
" " "" \
$(if echo "$service_state" | grep -q 'disabled'; then echo "Enable service x"; fi) \
$(if echo "$service_state" | grep -q 'enabled'; then echo "Disable service x"; fi) \
" " " " \
" " "" \
"Back to previous menu" "x" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $choice in
"View detailed service status")
loading "Getting Meshtasticd service status..."
echo "Getting Meshtasticd service status..."
dialog --no-collapse --title "Meshtasticd service status" --msgbox "$(systemctl status meshtasticd)" 0 0
;;
"Start/restart service")
dialog --no-collapse --title "$title" --yesno "Start/restart Meshtasticd service?" 6 45
if [ $? -eq 0 ]; then #unless cancel/no
femto-meshtasticd-config.sh -s
dialog --no-collapse --msgbox "Meshtasticd service started/restarted." 6 45
dialog --no-collapse --colors --msgbox "Sent \`\Zusystemctl restart meshtasticd\Zn\` command to system.\n\nMeshtasticd should be running." 9 50
fi
;;
"Stop service")
dialog --no-collapse --colors --title "$title" --yesno "Stop Meshtasticd service?\n\nThis will take the node \Zu\Z1OFFLINE\Zn.\n\nMeshtasticd will automatically restart on boot if not disabled." 11 50
dialog --no-collapse --colors --title "$title" --yesno "Stop Meshtasticd service?\n\nThis will take the node \Zu\Z1OFFLINE\Zn.\n\nMeshtasticd will automatically restart on boot service if enabled." 11 50
if [ $? -eq 0 ]; then #unless cancel/no
femto-meshtasticd-config.sh -t
dialog --no-collapse --msgbox "Meshtasticd service stopped." 6 45
dialog --no-collapse --colors --msgbox "Sent \`\Zusystemctl stop meshtasticd\Zn\` command to system.\n\nMeshtasticd should be stopped." 9 50
fi
;;
"Enable service")
@ -619,28 +605,55 @@ meshtastic_settings() {
dialog --no-collapse --colors --title "$title" --yesno "Disable Meshtasticd service?\n\nThis will take the node \Zu\Z1OFFLINE\Zn and will not restart!" 9 50
if [ $? -eq 0 ]; then #unless cancel/no
femto-meshtasticd-config.sh -M "disable"
dialog --no-collapse --colors --msgbox "Sent \`\Zusystemctl disable meshtasticd\Zn\` and \`\Zusystemctl stop meshtasticd\Zn\` commands to system.\n\nMeshtasticd is disabled and stopped." 10 50
dialog --no-collapse --colors --msgbox "Sent \`\Zusystemctl disable meshtasticd\Zn\` and \`\Zusystemctl stop meshtasticd\Zn\` commands to system.\n\nMeshtasticd should be disabled and stopped." 10 50
fi
;;
"Back to previous menu") break ;;
esac
done
;;
8) #Upgrade meshtasticd)
8) #i2c)
choice="" # zero the choice before loading the submenu
while true; do
i2c_state=$(femto-utils.sh -R "$(femto-meshtasticd-config.sh -I check)")
choice=$(dialog --no-collapse --colors --cancel-label "Back" --title "Meshtastic i2c Support" --default-item "$choice" --menu "i2c is used for sensors and displays.\nCurrently \Zu$i2c_state." 12 42 5 \
$(if echo "$i2c_state" | grep -q 'disabled'; then echo "Enable i2c x"; fi) \
$(if echo "$i2c_state" | grep -q 'enabled'; then echo "Disable i2c x"; fi) \
" " "" \
"Back" "x" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $choice in
"Enable i2c")
dialog --no-collapse --colors --title "Meshtastic i2c Support" --yesno "Enable i2c?\n\nEnabling i2c without devices connected will lead to slowdowns and error messages." 9 47
if [ $? -eq 0 ]; then #unless cancel/no
femto-meshtasticd-config.sh -I enable
fi
;;
"Disable i2c")
dialog --no-collapse --colors --title "Meshtastic i2c Support" --yesno "Disable i2c?\n\nDisabling i2c will only apply to Meshtastic, not to Foxbuntu." 9 50
if [ $? -eq 0 ]; then #unless cancel/no
femto-meshtasticd-config.sh -I disable
fi
;;
"Back") break ;;
esac
done
;;
9) #Upgrade meshtasticd)
dialog --no-collapse --title "$title" --yesno "Upgrade Meshtasticd?\nRequires internet connection." 0 0
if [ $? -eq 0 ]; then #unless cancel/no
femto-meshtasticd-config.sh -z
pause
fi
;;
9) #uninstall meshtasticd)
10) #uninstall meshtasticd)
dialog --no-collapse --colors --title "$title" --yesno "Uninstall Meshtasticd?\n\nFoxbuntu was designed with Meshtasticd integration in mind, and may behave unexpectedly if Meshtasticd is removed.\n\nThis will take the node \Zu\Z1OFFLINE\Zn and will not restart!" 0 0
if [ $? -eq 0 ]; then
femto-meshtasticd-config.sh -x
dialog --no-collapse --colors --msgbox "Meshtasticd uninstalled. To purge all remnants, run \`\Zusudo apt purge\Zn\`." 8 40
fi
;;
10)
11)
return
;;
esac
@ -664,12 +677,12 @@ help_menu() {
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $help_choice in
1) #About Femtofox)
dialog --no-collapse --title "About Femtofox" --default-item "$choice" --backtitle "Foxbuntu $(grep -oP 'major=\K[0-9]+' /etc/foxbuntu-release).$(grep -oP 'minor=\K[0-9]+' /etc/foxbuntu-release).$(grep -oP 'patch=\K[0-9]+' /etc/foxbuntu-release)$(grep -oP 'hotfix=\K[a-z]+' /etc/foxbuntu-release)" --msgbox "$(femto-license.sh -a)" 18 65
dialog --no-collapse --title "About Femtofox" --default-item "$choice" --backtitle "$(femto-utils.sh -v)" --msgbox "$(femto-license.sh -a)" 18 65
;;
2) #Display pinout)
choice="" # zero the choice before loading the submenu
while true; do
choice=$(dialog --no-collapse --cancel-label "Back" --item-help --menu "Pinouts" 15 40 5 \
choice=$(dialog --no-collapse --cancel-label "Back" --default-item "$choice" --item-help --menu "Pinouts" 15 40 5 \
1 "Femtofox Pro/CE" "" \
2 "Femtofox Zero" "" \
3 "Femtofox Tiny" "" \
@ -678,7 +691,7 @@ help_menu() {
5 "Back to Help Menu" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $choice in
1) dialog --no-collapse --title "Femtofox" --msgbox "$(femto-pinout.sh -f)" 43 68 ;;
1) dialog --no-collapse --title "Femtofox" --msgbox "$(femto-pinout.sh -f)" 42 68 ;;
2) dialog --no-collapse --title "Femtofox Zero" --msgbox "$(femto-pinout.sh -z)" 34 48 ;;
3) dialog --no-collapse --title "Femtofox Tiny" --msgbox "$(femto-pinout.sh -t)" 38 70 ;;
4) dialog --no-collapse --title "Luckfox Pico Mini" --msgbox "$(femto-pinout.sh -l)" 23 65 ;;
@ -687,7 +700,7 @@ help_menu() {
done
;;
3) #Femtofox licensing info - short)
dialog --no-collapse --title "Femtofox license" --msgbox "$(femto-license.sh -f)" 28 60
dialog --no-collapse --title "Femtofox license" --msgbox "$(femto-license.sh -f)" 31 65
;;
4) #Femtofox licensing info - long)
clear
@ -715,19 +728,31 @@ help="If script is run without arguments, femto-config menu will load.\n\
Options are:\n\
-h This message\n\
-l Set LoRa radio model menu\n\
-L Meshtastic legacy admin menu\n\
-w Set Wi-Fi config menu\
-c Check if Meshtasticd is running and warn the user if not\
"
while getopts ":hlwL:i" opt; do
while getopts ":hluLwc" opt; do
case ${opt} in
h) # Option -h (help)
echo -e $help
;;
;;
l) # Option -l (set lora radio)
set_lora_radio
;;
u) # Option -u (set meshtastic URL)
meshtastic_config_url
;;
L) # Option -L (Meshtastic legacy admin menu)
legacy_admin
;;
w) # Option -w (Wi-Fi config)
wifi_config
;;
c) # Option -c (Check if Meshtasticd is running and warn the user if not)
check_meshtasticd_running
exit $?
;;
\?) # Unknown option)
echo -e "Unknown argument $1.\n$help"
;;
@ -737,7 +762,7 @@ done
# Main menu
while true; do
main_menu_choice=$(dialog --no-collapse --cancel-label "Exit" --default-item "$main_menu_choice" --item-help --menu "Femtofox Config" 16 40 5 \
main_menu_choice=$(dialog --no-collapse --cancel-label "Exit" --backtitle "$(femto-utils.sh -v)" --default-item "$main_menu_choice" --item-help --menu "Femtofox Config" 16 40 5 \
1 "Settings wizard" "" \
2 "Networking" "" \
3 "Meshtastic" "" \
@ -758,4 +783,4 @@ while true; do
esac
done
exit 0
exit 0

View file

@ -19,107 +19,82 @@ wizard() {
femto-set-time.sh
new_hostname=$(dialog --title "$title" --cancel-label "Skip" --inputbox "Enter hostname:" 8 40 $(hostname) 3>&1 1>&2 2>&3)
new_hostname=$(dialog --title "Hostname" --cancel-label "Skip" --inputbox "Enter hostname:" 8 40 $(hostname) 3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then #unless cancel/no
femto-network-config.sh -n "$new_hostname"
dialog --title "$title" --msgbox "\nFemtofox is now reachable at\n$new_hostname.local" 8 40
dialog --title "Hostname" --msgbox "\nFemtofox is now reachable at\n$new_hostname.local" 8 40
fi
dialog --title "$title" --cancel-label "Skip" --yesno "\nConfigure Wi-Fi settings?" 8 40
dialog --title "$title" --yesno "Configure Wi-Fi settings?" 6 40
if [ $? -eq 0 ]; then #unless cancel/no
femto-config -w
fi
femto-config -l #set lora radio model
dialog --title "$title" --cancel-label "Skip" --yesno "\nConfigure Meshtastic?" 8 40
dialog --title "$title" --yesno "Configure Meshtastic?" 6 40
if [ $? -eq 0 ]; then #unless cancel/no
newurl=$(dialog --title "Meshtastic URL" --inputbox "New Meshtasticd URL (SHIFT+INS to paste):" 8 50 3>&1 1>&2 2>&3)
if [ -n "$newurl" ]; then #if a URL was entered
loading "Sending URL..."
dialog --no-collapse --colors --title "Meshtastic URL" --msgbox "$(femto-meshtasticd-config.sh -q "$newurl" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
if femto-config -c; then
while true; do
meshtastic_menu_choice=$(dialog --no-collapse --colors --cancel-label "Continue" --default-item "$meshtastic_menu_choice" --title "Meshtastic Configuration" --item-help --menu "Currently configured LoRa radio:\n$(femto-utils.sh -R "$(femto-meshtasticd-config.sh -k)")" 16 40 5 \
1 "Set LoRa radio model" "" \
2 "Set configuration URL" "" \
3 "Set private key" "" \
4 "Set public key" "" \
" " "" "" \
5 "Full Meshtastic settings menu" "" \
" " "" "" \
6 "Continue" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $meshtastic_menu_choice in
1) # Set LoRa radio model)
femto-config -l
;;
2) # Configure automatically with URL)
femto-config -c && (
femto-config -u
)
;;
3) # view/change private key)
femto-config -c && (
key=$(dialog --no-collapse --colors --title "Meshtastic Private Key" --cancel-label "Cancel" --inputbox "The private key of the device, used to create a shared key with a remote device for secure communication.\n\n\Z1This key should be kept confidential.\nSetting an invalid key will lead to unexpected behaviors.\Zn\n\nPrivate key (default: random)" 15 60 3>&1 1>&2 2>&3)
if [ $? -eq 0 ] && [[ -n "$key" ]]; then #unless cancel/no
loading "Sending command..."
dialog --no-collapse --colors --title "Meshtastic Private Key" --msgbox "$(femto-meshtasticd-config.sh -R "$key" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
)
;;
4) # view/change public key)
femto-config -c && (
key=$(dialog --no-collapse --colors --title "Meshtastic Public Key" --cancel-label "Cancel" --inputbox "The public key of the device, shared with other nodes on the mesh to allow them to compute a shared secret key for secure communication.\n\n\ZuGenerated automatically\Zn to match private key.\n\n\Z1Don't change this if you don't know what you're doing.\Zn\n\nPublic key (default: generated from private key)" 16 60 3>&1 1>&2 2>&3)
if [ $? -eq 0 ] && [[ -n "$key" ]]; then #unless cancel/no
loading "Sending command..."
dialog --no-collapse --colors --title "Meshtastic Public Key" --msgbox "$(femto-meshtasticd-config.sh -U "$key" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
)
;;
5) # Full Meshtastic settings menu)
femto-config -c && (
dialog --no-collapse --infobox "Loading Meshtastic settings menu...\n\nStopping conflicting services, will restart after exit...\n\nThis can take up to a minute." 9 50
femto-utils.sh -A stop
python /opt/control/main.py --host
femto-utils.sh -A start
)
;;
6) # return to previous menu)
break
;;
esac
done
fi
loading "Getting current public key..."
key=$(femto-meshtasticd-config.sh -u)
if [ -n "$key" ]; then
dialog --no-collapse --title "Meshtastic public key" --yesno "Current public key:\n$key\n\nSet new key?" 9 55
if [ $? -eq 0 ]; then #unless cancel/no
key=$(dialog --no-collapse --title "Meshtastic public key" --inputbox "New Meshtastic public key (SHIFT+INS to paste):" 8 60 3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then #unless cancel/no
loading "Sending command..."
dialog --no-collapse --colors --title "Meshtastic public key" --msgbox "$(femto-meshtasticd-config.sh -U "$key" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
fi
else
dialog --no-collapse --colors --title "Meshtastic public key" --msgbox "\Z1Failed to communicate with Meshtasticd.\Zn\n\nIs the service running?\n" 0 0
fi
loading "Getting current private key..."
key=$(femto-meshtasticd-config.sh -u)
if [ -n "$key" ]; then
dialog --no-collapse --title "Meshtastic private key" --yesno "Current private key:\n$key\n\nSet new key?" 9 55
if [ $? -eq 0 ]; then #unless cancel/no
key=$(dialog --no-collapse --title "Meshtastic private key" --inputbox "New Meshtastic private key (SHIFT+INS to paste):" 8 60 3>&1 1>&2 2>&3)
if [ $? -eq 0 ]; then #unless cancel/no
loading "Sending command..."
dialog --no-collapse --colors --title "Meshtastic private key" --msgbox "$(femto-meshtasticd-config.sh -R "$key" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
fi
else
dialog --no-collapse --colors --title "Meshtastic private key" --msgbox "\Z1Failed to communicate with Meshtasticd.\Zn\n\nIs the service running?\n" 0 0
fi
key=$(dialog --title "$title" --cancel-label "Skip" --inputbox "Enter Meshtastic admin key (optional). If 3 admin keys are already in Meshtastic, more will be ignored.\n(SHIFT+INS to paste):" 11 50 3>&1 1>&2 2>&3)
if [ -n "$key" ]; then #if a URL was entered
loading "Sending key..."
dialog --no-collapse --colors --title "Meshtastic URL" --msgbox "$(femto-meshtasticd-config.sh -A "$key" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
fi
dialog --no-collapse --infobox "Getting current legacy admin state..." 5 45
state=$(sudo femto-meshtasticd-config.sh -p)
if echo "$state" | grep -q "enabled"; then # poor man's replace ansi colors
state="\Z4enabled\Zn"
elif echo "$state" | grep -q "disabled"; then
state="\Z1disabled\Zn"
elif echo "$state" | grep -q "error"; then
state="\Z1error\Zn"
fi
while true; do
choice=$(dialog --no-collapse --colors --cancel-label "Skip" --title "Meshtasticd Legacy Admin" --menu "Current state: $state" 12 40 5 \
1 "Enable" \
2 "Disable (default)" \
"" "" \
3 "Skip" 3>&1 1>&2 2>&3)
exit_status=$? # This line checks the exit status of the dialog command
if [ $exit_status -ne 0 ]; then # Exit the loop if the user selects "Cancel" or closes the dialog
break
fi
case $choice in
1) # enable legacy admin)
dialog --no-collapse --infobox "Sending command..." 5 45
dialog --no-collapse --colors --title "$title" --msgbox "$(femto-meshtasticd-config.sh -o "true" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
break
;;
2) # disable legacy admin)
dialog --no-collapse --infobox "Sending command..." 5 45
dialog --no-collapse --colors --title "$title" --msgbox "$(femto-meshtasticd-config.sh -o "false" && echo -e "\n\Z4Command successful!\Zn\n" || echo -e "\n\Z1Command failed.\Zn\n")" 0 0
break
;;
3) break ;;
esac
done
fi
dialog --title "$title" --msgbox "\nSetup wizard complete!" 8 40
dialog --title "$title" --msgbox "Setup wizard complete!" 6 40
}
dialog --title "$title" --yesno "\
The install wizard will allow you to configure all the settings necessary to run your Femtofox.\n\
\n\
Running this wizard will overwrite some current settings.\n\n\
Proceed?" 13 50
The wizard takes several minutes to complete and will overwrite some current settings.\n\n\
Proceed?" 12 60
if [ $? -eq 0 ]; then #unless cancel/no
wizard
fi

View file

@ -1,13 +1,26 @@
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root."
echo "Try \`sudo femto-config\`."
exit 1
fi
help=$(cat <<EOF
If script is run without arguments, a dialog menu UI will load.
Options are:
-h This message
-b List kernel modules set to load at boot
-a List active kernel modules
-x "kernelmodule" "enable" Set kernel module status (enable/disable)
-z "kernelmodule" "blacklist" Set kernel module blacklist status (blacklist/un-blacklist)
-y Get list of blacklisted kernel modules
EOF
)
module_dir="/lib/modules/5.10.160"
title="Kernel Module Manager"
module_switch() {
if [ $2 = "enable" ]; then
modprobe $1 # Load the selected module
@ -15,76 +28,144 @@ module_switch() {
if ! grep -Fxq "$1" /etc/modules; then # Add the module to /etc/modules if not already present
echo "$1" >> /etc/modules
fi
echo "$1 has been enabled and will be started at boot."
echo -e "\033[4m$1\033[0m has been enabled and will be started at boot.\n\nSome modules are unloaded automatically when not in use."
else
echo -e "Failed to enable \033[4m$1\033[0m."
exit 1
fi
elif [ $2 = "disable" ]; then
rmmod $1 # Disable the module
if [ $? -eq 0 ]; then
sed -i "/^$1$/d" /etc/modules
echo "$1 has been disabled and removed from boot."
else
exit 1
fi
rmmod $1 > /dev/null 2>&1 # Unload the module
sed -i "/^$1$/d" /etc/modules
echo -e "\033[4m$1\033[0m has been disabled and removed from boot.\n\nIt may be automatically loaded if compatible hardware is detected."
else
echo "Invalid argument \"$2\".\n$help"
fi
}
module_blacklist() {
if [ $1 = "list" ]; then
echo -e "$(ls "$module_dir"/*.blacklisted 2>/dev/null | sed -E 's|.*/([^.]*)\..*|\1|' | awk '{for(i=1;i<=NF;i++) {printf "\033[4m%s\033[0m", $i; if(i<NF) printf " ";} printf " ";} END {if (NR == 0) print "\033[4mnone\033[0m"}')"
elif [ $2 = "blacklist" ]; then
mv "$module_dir/$1.ko" "$module_dir/$1.ko.blacklisted" > /dev/null 2>&1
module_switch $1 disable > /dev/null 2>&1 # unload and disable the module
echo -e "$1 is blacklisted. A reboot is sometimes required for blacklisting to fully take effect."
elif [ $2 = "un-blacklist" ]; then
mv "$module_dir/$1.ko.blacklisted" "$module_dir/$1.ko" > /dev/null 2>&1
echo -e "$1 is un-blacklisted. A reboot is sometimes required for un-blacklisting to fully take effect."
else
echo "Invalid argument \"$1 $2\".\n$help"
fi
}
# Parse options
while getopts ":hx" opt; do
while getopts ":hbax:z:y" opt; do
case ${opt} in
h) # Option -l (set lora radio)
echo "$help"
exit 0
;;
b) # kernel modules set to start at boot)
echo -e "$(modules=$(sed -n '6,$p' /etc/modules | awk '{printf "\033[4m%s\033[0m ", $0}'); [ -z "$modules" ] && echo "\033[4mnone\033[0m" || echo "$modules")"
;;
a) # kernel modules currently active)
echo -e "$(modules=$(lsmod | awk 'NR>1 {printf "\033[4m%s\033[0m ", $1}'); [ -z "$modules" ] && echo "none" || echo "$modules")"
;;
x) # Option -x (Set kernel module status (enable/disable))
echo "$(module_switch $2 $3)"
;;
z) # Option -z (Set kernel module blacklist status (blacklist/un-blacklist))
echo "$(module_blacklist $2 $3)"
;;
y) # Option -y (Get list of blacklisted kernel modules)
echo "$(module_blacklist "list")"
;;
esac
done
if [ -n "$1" ]; then # if there are arguments, don't proceed to menu
exit
fi
dialog --infobox "Loading kernel module menu..." 5 45
dialog --no-collapse --colors --title "$title" --yesno "\
Kernel modules are loadable pieces of code that extend a Linux kernel's functionality without requiring a reboot. Common examples include device drivers, file systems, or system calls.\n\
\n\
This tool will allow you to manage kernel modules and add pre-compiled modules to Foxbuntu.\n\
\n\
Boot modules: $(femto-utils.sh -R "$(femto-kernel-modules.sh -b)")\n\
Blacklisted modules: $(femto-utils.sh -R "$(femto-kernel-modules.sh -y)")\n\
Active modules: $(femto-utils.sh -R "$(femto-kernel-modules.sh -a)")\n\
\n\
Continue?
" 0 0
[ ! $? -eq 0 ] && exit 1
modules=()
load_modules() {
dialog --infobox "Loading kernel module menu...\n\nExpected load time: 35 seconds." 6 45
modules=("Module name" "L/D Description" "" "")
# Create a list of modules (filename minus the .ko)
for module in $(ls "/lib/modules/5.10.160"/*.ko); do
module_name=$(basename "$module" .ko)
modules+=("$module_name" "$(modinfo $module_name | grep -i 'description' | cut -d: -f2 | sed 's/^[ \t]*//')")
done
# Create a list of modules (filename minus the .ko)
for module in $(ls $module_dir/*.ko*); do
module_name=$(basename "$module" | sed 's/\([^.]*\).*/\1/')
modules+=("$module_name" "$(lsmod | grep -q "^$module_name " && echo ✅ || echo ❌)$(femto-kernel-modules.sh -b | sed 's/\x1b\[[0-9;]*m//g' | grep -qw "$module_name" && echo ✅ || echo ❌) $(basename "$module" | grep -q "blacklisted" && echo "BLACKLISTED" || modinfo "$module_name" | grep -i 'description' | cut -d: -f2 | sed 's/^[ \t]*//' )")
done
modules_changed="false"
}
load_modules
modules_changed="false"
while true; do
[ $modules_changed = "true" ] && load_modules
# Create the menu options
option=$(dialog --cancel-label "Back" --title "Kernel Modules" --default-item "$selected_module" --menu "" 42 103 8 "${modules[@]}" 3>&1 1>&2 2>&3)
exit_status=$? # Check the exit status of the dialog command
if [ $exit_status -ne 0 ]; then # Exit the loop if the user selects "Cancel" or closes the dialog
selected_module=$(dialog --no-collapse --cancel-label "Return" --ok-label "Open" --title "$title" --no-shadow --default-item "$selected_module" --help-button --menu "" 42 103 8 "${modules[@]}" 3>&1 1>&2 2>&3)
exit_status=$?
if [ $exit_status -eq 1 ]; then # "Return" button
break
fi
# Get the module name from the selection
selected_module=$option
# Get the full modinfo for the module and process it for dialog
modinfo_output=$(modinfo $selected_module | sed ':a;N;$!ba;s/\n/\\n/g') # add \n to module info
# Check if the module is currently enabled
if lsmod | grep -q "^$selected_module "; then
dialog --colors --title "Disable Module" --yesno "The module '$selected_module' is currently \Z4\Zuenabled\Zn.\n\nDo you want to disable it?\n\nFull module info:\n$modinfo_output\n\nNote: Unused dependencies will be removed automatically." 25 0
if [ $? -eq 0 ]; then
dialog --msgbox "$(module_switch $selected_module disable)" 7 60
fi
elif [ $exit_status -eq 2 ]; then # "Help" button
dialog --no-collapse --colors --title "Kernel Module Manager Help" --msgbox "In the kernel module manager menu,\nL=Module is loaded\nB=Module is set to start at boot.\n\nIf module is blacklisted, \`BLACKLISTED\` will show in the description." 0 0
else
dialog --colors --title "Enable Module" --yesno "The module '$selected_module' is currently \Z1disabled\Zn.\n\nDo you want to enable it?\n\nFull module info:\n$modinfo_output\n\nNote: Dependencies will be loaded automatically." 25 0
if [ $? -eq 0 ]; then
dialog --msgbox "$(module_switch $selected_module enable)" 7 60
fi
[ "$selected_module" = "" ] || [ "$selected_module" = "Module name" ] && continue # do nothing if no valid module name is selected
modules_changed="false"
# Get the full modinfo for the module and process it for dialog
while true; do
modinfo_output=$(modinfo $selected_module 2>/dev/null | sed ':a;N;$!ba;s/\n/\\n/g') # add \n to module info
if [ ! -e "$module_dir/$selected_module.ko" ]; then
module_info="\Z1\ZuMODULE BLACKLISTED!\Zn\n\n$selected_module has been blacklisted and will not load on boot.\
$(lsmod | grep -q "^$selected_module " && echo "\n\n$selected_module is currently \Z4\Zuloaded\Zn!\n\
Some modules require reboot for blacklist to take effect if they're in use when blacklisted.")"
else
module_info="Module is currently $(lsmod | grep -q "^$selected_module " && echo "\Z4loaded\Zn" || echo "\Z1unloaded\Zn") and is set $(femto-utils.sh -R "$(femto-kernel-modules.sh -b | sed 's/\x1b\[[0-9;]*m//g' | grep -qw "$selected_module" && echo "\Z4to load at boot\Zn" || echo "\Z1not to load at boot\Zn. It may load automatically if needed")").\n\
\n\
Full module info:\n$modinfo_output\n\nNote: Dependencies are loaded/unloaded automatically."
fi
dialog --colors --yes-label "Return" --no-label "Disable" --extra-button --extra-label "Enable" --help-button --help-label "Blacklist" --title "$selected_module" --yesno "$module_info" 0 0
exit_status=$? # This line checks the exit status of the dialog command
if [ $exit_status -eq 0 ]; then # "Back" button
break
elif [ $exit_status -eq 3 ]; then # "Enable" button
dialog --colors --title "$selected_module" --msgbox "$(femto-utils.sh -R "$(module_switch $selected_module enable)")" 0 0
modules_changed="true"
elif [ $exit_status -eq 1 ]; then # "Disable" button
dialog --colors --title "$selected_module" --msgbox "$(femto-utils.sh -R "$(module_switch $selected_module disable)")" 0 0
modules_changed="true"
elif [ $exit_status -eq 2 ]; then # "Blacklist" button
dialog --no-collapse --colors --title "$selected_module" --yes-label "Return" --no-label "Un-blacklist" --extra-button --extra-label "Blacklist" --yesno "$selected_module is currently $([ -e "$module_dir/$selected_module.ko" ] && echo "\Z4\Zunot blacklisted\Zn" || echo "\Z1\Zublacklisted\Zn").\n\nBlacklisting prevents a kernel module from loading.\n\nWould you like to blacklist $selected_module?" 0 0
exit_status=$?
if [ $exit_status -eq 0 ]; then
continue
elif [ $exit_status -eq 3 ]; then # blacklist
dialog --colors --title "$selected_module" --msgbox "$(femto-utils.sh -R "$(module_blacklist $selected_module blacklist)")" 8 50
modules_changed="true"
else # blacklist
dialog --colors --title "$selected_module" --msgbox "$(femto-utils.sh -R "$(module_blacklist $selected_module un-blacklist)")" 8 50
modules_changed="true"
fi
fi
done
fi
done
exit 0
exit 0

View file

@ -11,26 +11,30 @@ Options are:
EOF
)
anykey="echo -e \"\nPress any key to continue...\n\" && read -n 1 -s -r"
pause() {
echo -e "\nPress any key to continue..."
read -n 1 -s -r
}
femtofox_short_license="\
Femtofox and Foxbuntu are published under CC BY-NC-ND - noncommercial.\n\
Femtofox is comprised of two projects, with two different licenses:\n\
1. Femtofox - the hardware, which is licensed \"CC BY-NC-ND - noncommercial\". Summary: you may copy and share and modify the hardware files, but cannot sell them without license from Femtofox, and must give attribution to Femtofox.\n\
2. Foxbuntu - refers to the modifications to Ubuntu made as part of the Femtofox project, which is licensed GNU GPLv3. Summary: you may use, modify and distribute (including for commercial purposes) Foxbuntu, but must give attribution to Femtofox and distribute this license with your project. Any modified version must remain open source.\n\
\n\
For more information, visit us at www.femtofox.com.\n\
\n\
Summary:\n\
You can share Femtofox and Foxbuntu or make modifications, but can't sell it except by arrangement (license) with us.\n\
In this context, Foxbuntu refers to the modifications to Ubuntu made as part of the Femtofox project.\n\
\n\
Boilerplate:\n\
Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made.\n\
You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.\n\
NonCommercial — You may not use the material for commercial purposes.\n\
NoDerivatives — If you remix, transform, or build upon the material, you may not distribute the modified material (for commercial purposes).\n\
\n\
View the long licenses for more information.\n\
Contact us to license Femtofox."
meshtastic_license="\
Meshtastic is a registered trademark of Meshtastic LLC. Meshtastic software components are released under various licenses, see GitHub for details. No warranty is provided - use at your own risk."
The Meshtastic firmware is licensed GPL3.\n\
\n\
Meshtastic is a registered trademark of Meshtastic LLC. Meshtastic software components are released under various licenses, see GitHub for details. No warranty is provided - use at your own risk.\n\
\n\
Some of the verbiage in the help-texts in the menus is sourced from the Meshtastic website, also licensed GPL3.\n\
\n\
For more information about Meshtastic, visit https://www.meshtastic.org\
"
luckfox_license="Luckfox and Luckfox Pico Mini are property of Luckfox Technology. Femtofox does not represent Luckfox Technology in any way, shape or form. Visit their website at https://www.luckfox.com/."
@ -91,7 +95,7 @@ https://www.femtofox.com\n\
u) # Option -u (Ubuntu licenses)
echo "$ubuntu_license"
;;
\?) # Invalid option
\?) # Invalid option)
echo "Invalid option: -$OPTARG"
echo -e "$help"
exit 1
@ -102,13 +106,13 @@ done
# if no arguments, show all licenses
if [ $# -eq 0 ]; then
echo "$femtofox_short_license"
eval $anykey
pause
echo "$(cat /usr/share/doc/femtofox/long_license)"
eval $anykey
pause
echo "$meshtastic_license"
eval $anykey
pause
echo "$luckfox_license"
eval $anykey
pause
eval "$ubuntu_license"
eval $anykey
pause
fi

View file

@ -8,6 +8,7 @@ help=$(cat <<EOF
Options are:
-h This message
-i Get important node info
-C "all" Get node configuration, by category. Multiple categories can be selected by comma delineation. \`quiet\`: do not echo to console. Options are \`quiet\`, \`all\`, \`nodeinfo\`, \`settings\`, \`channels\`
-g Gets the current configuration URL and QR code
-k Get current LoRa radio selection
-l "RADIO" Choose LoRa radio model. Options are \`lr1121_tcxo\`, \`sx1262_tcxo\`, \`sx1262_xtal\`, \`none\` (simradio)
@ -26,6 +27,7 @@ Options are:
-t Stop Meshtasticd service
-M "enable" Enable/disable Meshtasticd service. Options: "enable" "disable"
-S Get Meshtasticd service state
-I "enable" Manage i2c state. Options: "enable" "disable" "check"
-z Upgrade Meshtasticd
-x Uninstall Meshtasticd
-m Meshtastic update tool. Syntax: \`femto-meshtasticd-config.sh -m \"--set security.admin_channel_enabled false\" 10 \"Disable legacy admin\"\`
@ -43,16 +45,17 @@ meshtastic_update() {
local command="$1"
local attempts=$2
local ref="$3: "
echo "${ref:+$ref}meshtastic --host $command"
echo "Submitting to Meshtastic..."
for retries in $(seq 1 $attempts); do
local output=$(meshtastic --host $command) #>&2 lets meshtastic's output display on screen
echo $output
logger $output
if echo "$output" | grep -qiE "Abort|invalid|Error|refused|Errno"; then
output=$(eval meshtastic --host $command 2>&1 | tee /dev/fd/2) # display the output on screen live. Use eval so quotes will be handled correctly in $command
logger "$output"
if echo "$output" | grep -qiE "Abort|invalid|Error|error|unrecognized|refused|Errno|failed|Failed"; then
if [ "$retries" -lt $attempts ]; then
local msg="${ref:+$ref}Meshtastic command failed, retrying ($(($retries + 1))/$attempts)..."
echo "$msg"
logger "$msg"
femto-meshtasticd-config.sh -s
sleep 2 # Add a small delay before retrying
fi
else
@ -67,6 +70,7 @@ meshtastic_update() {
fi
done
if [ -z "$success" ]; then
echo -e "$output"
msg="${ref:+$ref}Meshtastic command FAILED."
echo "$msg"
logger "$msg"
@ -74,53 +78,146 @@ meshtastic_update() {
fi
}
get_meshtastic_settings() {
for retries in $(seq 1 3); do
if meshtastic_info=$(meshtastic --host --info); then # if successful
success="true"
break
else # if failed
if [ "$retries" -lt 3 ]; then # if under 3 retries
echo "Meshtastic command failed, retrying ($(($retries + 1))/3)..."
femto-meshtasticd-config.sh -s
sleep 2 # Add a small delay before retrying
fi
fi
done
if [ -z "$success" ]; then # if failed all retries
echo "Meshtastic command FAILED."
exit 1 # always exit script if failed
fi
if [[ "$1" == *"all"* ]] || [[ "$1" == *"nodeinfo"* ]]; then
# myInfo
eval "myInfo_owner='$(echo "$meshtastic_info" | grep "^Owner: " | sed 's/^Owner: //')'"
[[ "$1" != *"quiet"* ]] && echo "myInfo_owner:$myInfo_owner"
while IFS="=" read -r varname value; do
eval "myInfo_$varname='$value'" # Create a variable with the formatted name
[[ "$1" != *"quiet"* ]] && echo "myInfo_$varname:$value"
done < <(
echo "$(echo "$meshtastic_info" | grep '^My info: ' | sed 's/^My info: //')" |
jq -r 'to_entries[] | "\(.key)=\(.value)"'
)
# metadata
while IFS="=" read -r varname value; do
eval "metadata_$varname='$value'" # Create a variable with the formatted name
[[ "$1" != *"quiet"* ]] && echo "metadata_$varname:$value"
done < <(
echo "$(echo "$meshtastic_info" | grep '^Metadata: ' | sed 's/^Metadata: //')" |
jq -r 'to_entries[] | "\(.key)=\(.value)"'
)
metadata_nodedbCount=$(echo "$meshtastic_info" | grep -oP '"![a-zA-Z0-9]+":\s*\{' | wc -l)
[[ "$1" != *"quiet"* ]] && echo "metadata_nodedbCount:$metadata_nodedbCount"
# nodeinfo
while IFS='=' read -r var value; do
eval "nodeinfo_$var=\"$value\""
[[ "$1" != *"quiet"* ]] && echo "nodeinfo_$var:$value"
done < <(echo "$(echo "$meshtastic_info" | sed -n '/Nodes in mesh:/,$p' | sed '1s/^Nodes in mesh: *//' | sed '/^[[:space:]]*$/q' | jq -r 'to_entries | .[0] | "\(.key)=\(.value)"' | sed 's/^[^=]*=//;s/^[ \t]*}//')" | jq -r '
def recurse:
if type == "object" then
to_entries | .[] | "\(.key)=\(.value | recurse)"
elif type == "array" then
. | tostring
else
.
end;
recurse' | sed '/=/ {s/\(.*\)=\(.*\)=/\1_\2=/; }'
)
fi
if [[ "$1" == *"all"* ]] || [[ "$1" == *"settings"* ]]; then
# settings
while IFS="=" read -r varname value; do
eval "$varname='$value'"
[[ "$1" != *"quiet"* ]] && echo "$varname:$value"
done < <(
echo "$(echo "$meshtastic_info" | sed -n '/Preferences: {/,$p' | sed '1s/.*/{/; /^[[:space:]]*$/q')" |
jq -r 'to_entries[] | select(.value | type == "object") | .key as $block | .value | to_entries[] | "\($block)_\(.key)=\(.value)"'
)
# module settings
while IFS="=" read -r varname value; do
eval "$varname='$value'"
[[ "$1" != *"quiet"* ]] && echo "$varname:$value"
done < <(
echo "$(echo "$meshtastic_info" | sed -n '/Module preferences: {/,$p' | sed '1s/.*/{/; /^[[:space:]]*$/q')" |
jq -r 'to_entries[] | select(.value | type == "object") | .key as $block | .value | to_entries[] | "\($block)_\(.key)=\(.value)"'
)
fi
if [[ "$1" == *"all"* ]] || [[ "$1" == *"channels"* ]]; then
# channels
while read index line; do
channel_type=$(echo "$line" | awk '{print $3}')
psk_type=$(echo "$line" | grep -o 'psk=[^ ]*' | cut -d= -f2)
eval "channel${index}_type='$channel_type'"
[[ "$1" != *"quiet"* ]] && echo "channel${index}_type:$channel_type"
eval "channel${index}_psk_type='$psk_type'"
[[ "$1" != *"quiet"* ]] && echo "channel${index}_psk_type:$psk_type"
# get the json portion of the channel listing
while IFS=":" read -r key value; do
eval "$key='$value'"
[[ "$1" != *"quiet"* ]] && echo "$key:$value"
done < <(
echo "$(echo "$line" | sed 's/.*\({.*\)/\1/')" | jq -r 'to_entries | .[] | "channel'${index}'_\(.key):\(.value)"'
)
done < <(
echo "$meshtastic_info" | awk '/Channels:/ {f=1; next} f && NF {print} f && !NF {exit}' | nl -v 0
)
eval "url_primary_channel='$(echo "$meshtastic_info" | sed -n 's/^Primary channel URL: //p')'"
[[ "$1" != *"quiet"* ]] && echo "url_primary_channel:$url_primary_channel"
if echo "$meshtastic_info" | grep -q "^Complete URL (includes all channels): "; then
url_all_channels=$(echo "$meshtastic_info" | sed -n 's/^Complete URL (includes all channels): //p')
[[ "$1" != *"quiet"* ]] && echo "url_all_channels:$url_all_channels"
fi
fi
}
# Parse options
while getopts ":higkl:q:uU:rR:aA:cpo:sM:Stwuxm" opt; do
while getopts ":hiC:gkl:q:uU:rR:aA:cpo:sM:StI:wuzxm" opt; do
case ${opt} in
h) # Option -h (help)
echo -e "$help"
;;
i) # Option -i (Get important node info)
declare -a output_array
output=$(meshtastic --host --info)
output_array+=("Service=$(femto-meshtasticd-config.sh -S)")
output_array+=("Version=$(echo "$output" | grep -oP '"firmwareVersion":\s*"\K[^"]+' | head -n 1)")
output_array+=("Node name=$(echo "$output" | grep -oP 'Owner:\s*\K.*' | head -n 1)")
output_array+=("NodeID=$(echo "!$(printf "%08x\n" $(echo "$output" | grep -oP '"myNodeNum":\s*\K\d+' | head -n 1))")")
output_array+=("Nodenum=$(echo "$output" | grep -oP '"myNodeNum":\s*\K\d+' | head -n 1)")
output_array+=("TX enabled=$(echo "$output" | grep -oP '"txEnabled":\s*\K\w+')")
use_preset=$(echo "$output" | grep -oP '"usePreset":\s*\K\w+')
output_array+=("Use preset=$use_preset")
if [ "$use_preset" = "true" ]; then # if use-preset is true, then display the preset
output_array+=("Preset=$(echo "$output" | grep -oP '"modemPreset":\s*"\K[^"]+')")
else # otherwise, display the lora settings
output_array+=("Bandwidth=$(echo "$output" | grep -oP '"bandwidth":\s*\K\w+')")
output_array+=("Spread factor=$(echo "$output" | grep -oP '"spreadFactor":\s*\K\w+')")
output_array+=("Coding rate=$(echo "$output" | grep -oP '"codingRate":\s*\K\w+')")
fi
output_array+=("Role=$(echo "$output" | grep -oP '"role":\s*"\K[^"]+' | head -n 1)")
freq_offset=$(echo "$output" | grep -oP '"bandwidth":\s*\K\w+')
if [ "$freq_offset" != 0 ]; then # only display frequency offset if not 0
output_array+=("Override freq=$freq_offset")
fi
output_array+=("Region=$(echo "$output" | grep -oP '"region":\s*"\K[^"]+')")
output_array+=("Hop limit=$(echo "$output" | grep -oP '"hopLimit":\s*\K\w+')")
freq_slot=$(echo "$output" | grep -oP '"channelNum":\s*\K\d+' | head -n 1)
if [ "$freq_slot" != 0 ]; then # only display frequency slot if not 0
freq_slot+=("Freq slot=$freq_slot")
fi
override_freq=$(echo "$output" | grep -oP '"overrideFrequency":\s*\K[0-9.]+')
if [ "$override_freq" != "0" ]; then # only display override frequency if not 0
output_array+=("Override freq=$override_freq")
fi
output_array+=("Public key=$(echo "$output" | grep -oP '"publicKey":\s*"\K[^"]+' | head -n 1)")
output_array+=("Nodes in db=$(echo "$output" | grep -oP '"![a-zA-Z0-9]+":\s*\{' | wc -l)")
# now, echo the array
for pair in "${output_array[@]}"; do
key=$(echo "$pair" | cut -d'=' -f1)
value=$(echo "$pair" | cut -d'=' -f2-)
echo "$key:$value"
done
get_meshtastic_settings quiet,nodeinfo,settings
echo -e "\
Service:$(femto-meshtasticd-config.sh -S)
Version:$metadata_firmwareVersion
Node name:$myInfo_owner
NodeID:$nodeinfo_user_id
Nodenum:$myInfo_myNodeNum
TX enabled:$lora_txEnabled
Use preset:$lora_usePreset
Preset:$lora_modemPreset
Bandwidth:$lora_bandwidth
Spread factor:$lora_spreadFactor
Coding rate:$lora_codingRate
Role:$device_role
Freq offset:$lora_frequencyOffset
Region:$lora_region
Hop limit:$lora_hopLimit
Freq slot:$lora_channelNum
Override freq:$lora_overrideFrequency
Public key:$security_publicKey
Nodes in db:$metadata_nodedbCount"
;;
C) # Option -C (Complete node config)
get_meshtastic_settings $OPTARG
;;
g) # Option -g (get config URL)
url=$(meshtastic --host --qr-all | grep -oP '(?<=Complete URL \(includes all channels\): )https://[^ ]+') #add look for errors
@ -130,7 +227,7 @@ while getopts ":higkl:q:uU:rR:aA:cpo:sM:Stwuxm" opt; do
echo $url
;;
k) # Option -k (get current lora radio model)
ls /etc/meshtasticd/config.d 2>/dev/null | xargs -r -n 1 basename | sed 's/^femtofox_//;s/\.yaml$//' | grep . || echo -e "\033[0;31mnone (simulated radio)\033[0m"
ls /etc/meshtasticd/config.d 2>/dev/null | grep '^femtofox_' | xargs -r -n 1 basename | sed 's/^femtofox_//;s/\.yaml$//' | grep . || echo -e "\033[0;31mnone (simulated radio)\033[0m"
;;
l) # Option -l (choose lora radio model)
prepare="rm -f /etc/meshtasticd/config.d/femtofox* && echo \"Radio type $OPTARG selected.\""
@ -146,11 +243,15 @@ while getopts ":higkl:q:uU:rR:aA:cpo:sM:Stwuxm" opt; do
eval $prepare
cp /etc/meshtasticd/available.d/femtofox/femtofox_SX1262_XTAL.yaml /etc/meshtasticd/config.d
systemctl restart meshtasticd
elif [ "$OPTARG" = "lora-meshstick-1262" ]; then
eval $prepare
cp /etc/meshtasticd/available.d/lora-meshstick-1262.yaml /etc/meshtasticd/config.d/femtofox_lora-meshstick-1262.yaml # ugly code for the special case of the meshstick, which is not femto. Allows it to be detected by femto scripts and removed if radio changes
systemctl restart meshtasticd
elif [ "$OPTARG" = "none" ]; then
eval $prepare
systemctl restart meshtasticd
else
echo "$OPTARG is not a valid option. Options are \`lr1121_tcxo\`, \`sx1262_tcxo\`, \`sx1262_xtal\`, \`none\` (simradio)"
echo "$OPTARG is not a valid option. Options are \`lr1121_tcxo\`, \`sx1262_tcxo\`, \`sx1262_xtal\`, \`lora-meshstick-1262\`, \`none\` (simradio)"
fi
;;
q) # Option -q (set config URL)
@ -220,22 +321,32 @@ while getopts ":higkl:q:uU:rR:aA:cpo:sM:Stwuxm" opt; do
fi
;;
S) # Option -S (Get Meshtasticd Service state)
if systemctl is-enabled meshtasticd &>/dev/null; then
if echo "$(systemctl status meshtasticd)" | grep -q "active (running)"; then
echo -e "\033[4m\033[0;34menabled and running\033[0m"
elif echo "$(systemctl status meshtasticd)" | grep -q "inactive (dead)"; then
echo -e "\033[4m\033[0;31menabled but not running\033[0m"
else
echo "unknown"
fi
else
echo -e "\033[4m\033[0;31mdisabled\033[0m"
fi
femto-utils.sh -C "meshtasticd" # this functionality has been moved
;;
t) # Option -t (stop Meshtasticd service)
systemctl stop meshtasticd
echo "Meshtasticd service stopped."
;;
I) # Option -I (Manage i2c state. Options: "enable" "disable" "check")
yaml_file="/etc/meshtasticd/config.d/femto_config.yaml"
if [ "$OPTARG" = "enable" ]; then
echo -e "\nI2C:\n I2CDevice: /dev/i2c-3" >> $yaml_file
femto-meshtasticd-config.sh -s
elif [ "$OPTARG" = "disable" ]; then
sed -i '/I2C:/,/I2CDevice: \/dev\/i2c-3/d' $yaml_file
femto-meshtasticd-config.sh -s
elif [ "$OPTARG" = "check" ]; then
if grep -q "I2C:" $yaml_file && grep -q "I2CDevice: /dev/i2c-3" $yaml_file; then
echo -e "\033[0;34menabled\033[0m"
else
echo -e "\033[0;31mdisabled\033[0m"
fi
else
echo "Invalid argument \`-I $OPTARG\`. Options are \`enable\` \`disable\` \`check\`."
echo -e "$help"
exit 1
fi
;;
z) # Option -z (upgrade meshtasticd)
apt update
apt install --only-upgrade meshtasticd

View file

@ -0,0 +1,501 @@
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Try \`sudo femto-meshtasticd-config\`."
exit 1
fi
export NCURSES_NO_UTF8_ACS=1
export TERM=xterm-256color
export LANG=C.UTF-8
title="Meshtastic LoRa Settings"
args=$@
send_settings() {
if [ -n "$command" ]; then
set -o pipefail
echo "meshtastic --host $command"
output=$(eval "femto-meshtasticd-config.sh -m '$command' 5 'Save Meshtastic settings'" | tee /dev/tty)
exit_status=$?
set +o pipefail
if [ $exit_status -eq 1 ]; then
dialog --no-collapse --colors --title "$title" --msgbox "$(echo -e "\Z1Command FAILED!\Zn\n\nLog:\n$output")" 0 0
elif [ $exit_status -eq 0 ]; then
dialog --no-collapse --colors --title "$title" --msgbox "$(echo -e "\Z4Command Successful!\Zn\n\nLog:\n$output")" 0 0
fi
fi
[ "$1" = "wizard" ] && [ -z "$args" ] && dialog --no-collapse --title "$title" --colors --msgbox "Meshtastic LoRa Settings Wizard complete!" 6 50 # if in wizard mode AND there are no script arguments, display the message
}
config_url() {
femto-config -c && (
newurl=$(dialog --no-collapse --colors --title "Meshtastic URL" --inputbox "The Meshtastic configuration URL allows for automatic configuration of all Meshtastic LoRa settings and channels.\nEntering a URL may \Z1\ZuOVERWRITE\Zn your LoRa settings and channels!\n\nNew Meshtastic LoRa configuration URL (SHIFT+INS to paste):" 13 63 3>&1 1>&2 2>&3)
if [ -n "$newurl" ]; then #if a URL was entered
command+="--seturl $newurl "
fi
# if we're in wizard mode AND there are no script arguments, then display a message
send_settings $1
)
}
lora_settings_actions() {
if [ "$1" = "set_lora_radio_model" ] || [ "$1" = "wizard" ]; then
choice="" # zero the choice before loading the submenu
while true; do
echo "Checking LoRa radio..."
#Display filename, if exists: $(files=$(ls /etc/meshtasticd/config.d/* 2>/dev/null) && [ -n "$files" ] && echo "\n\nConfiguration files in use:\n$files" | paste -sd, -))
choice=$(dialog --no-collapse --colors --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --default-item "$choice" --title "Meshtastic LoRa radio" --item-help --menu "Currently configured LoRa radio:\n$(femto-utils.sh -R "$(femto-meshtasticd-config.sh -k)")$(ls -1 /etc/meshtasticd/config.d 2>/dev/null | grep -v '^femto_' | paste -sd ', ' - | sed 's/^/ (/; s/$/)/; s/,/, /g' | grep -v '^ ()$')" 22 50 10 \
"Radio name:" "Configuration:" "" \
"" "" "" \
"Ebyte e22-900m30s" "(SX1262_TCXO)" "Included in Femtofox Pro" \
"Ebyte e22-900m22s" "(SX1262_TCXO)" "" \
"Ebyte e80-900m22s" "(SX1262_XTAL)" "" \
"Heltec ht-ra62" "(SX1262_TCXO)" "" \
"Seeed wio-sx1262" "(SX1262_TCXO)" "" \
"Waveshare sx126x-xxxm" "(SX1262_XTAL)" "Not recommended due issues with sending longer messages" \
"AI Thinker ra-01sh" "(SX1262_XTAL)" "" \
"LoRa Meshstick 1262" "(meshstick-1262)" "USB based LoRa radio from Mark Birss. https://github.com/markbirss/MESHSTICK" \
"Simulated radio" "(none)" "" \
" " "" "" \
"$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" "" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
local radio=""
case $choice in
"Ebyte e22-900m30s")
radio="sx1262_tcxo"
;;
"Ebyte e22-900m22s")
radio="sx1262_tcxo"
;;
"Ebyte e80-900m22s")
radio="sx1262_xtal"
;;
"Heltec ht-ra62")
radio="sx1262_tcxo"
;;
"Seeed wio-sx1262")
radio="sx1262_tcxo"
;;
"Waveshare sx126x-xxxm")
radio="sx1262_xtal"
;;
"AI Thinker ra-01sh")
radio="femto_sx1262_xtal"
;;
"LoRa Meshstick 1262")
radio="lora-meshstick-1262"
;;
"Simulated radio")
radio="none"
;;
"Skip")
return
;;
esac
if [ -n "$radio" ]; then #if a radio was selected
femto-meshtasticd-config.sh -l "$radio" -s # set the radio, then restart meshtasticd
dialog --no-collapse --colors --title "$title" --msgbox "$(echo -e "Radio \Zu$choice\Zn selected.\nMeshtasticd service restarted.\Zn")" 7 45
break
fi
done
[ "$1" = "set_lora_radio_model" ] && return
fi
if femto-config -c; then
if [ "$1" = "wizard" ]; then
choice="" # zero the choice before loading the submenu
while true; do
choice=$(dialog --no-collapse --title "$title" --cancel-label "Cancel" --default-item "True" --item-help --menu "Meshtastic configuration method" 8 50 0 \
"Automatic configuration with URL" "" "" \
"Manual configuration" "" "" \
" " "" "" \
"Cancel" "" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] || [ "$choice" == "Cancel" ] && return # Exit the loop if the user selects "Cancel" or closes the dialog
[ "$choice" == "" ] && continue #restart loop if no choice made
[ "$choice" == "Manual configuration" ] && break
[ "$choice" == "Automatic configuration with URL" ] && config_url "$1"
return
done
fi
dialog --no-collapse --infobox "Getting current settings from Meshtasticd.\n\nThis can take a minute..." 6 50
while IFS=':' read -r key value; do
eval "${key}=\"${value}\"" # Create a variable with the key name and assign it the value
done < <(sudo femto-meshtasticd-config.sh -C settings)
if [ "$1" = "region" ] || [ "$1" = "wizard" ]; then
options=("UNSET" "US" "EU_433" "EU_868" "CN" "JP" "ANZ" "KR" "TW" "RU" "IN" "NZ_865" "TH" "LORA_24" "UA_433" "UA_868" "MY_433" "MY_919" "SG_923")
menu_items=()
# Create menu options from the array
for i in "${!options[@]}"; do
if [ $i -eq 0 ]; then
menu_items+=("${options[$i]}" "(default)" "") # First item with "(default)"
else
menu_items+=("${options[$i]}" "" "") # Other items without "(default)"
fi
done
menu_items+=("" "" "" "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" "" "")
while true; do
choice=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --default-item "$lora_region" --item-help --menu "Sets the region for your node. As long as this is not set, the node will display a message and not transmit any packets.\n\nRegion? (current: ${lora_region})" 0 0 0 \
"${menu_items[@]}" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] || [ "$choice" == "Cancel" ] || [ "$choice" == "Skip" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
[ "$choice" == "" ] && continue # Restart loop if no choice made
command+="--set lora.region $choice "
break
done
fi
if [ "$1" = "use_modem_preset" ] || [ "$1" = "wizard" ]; then
choice="" # zero the choice before loading the submenu
while true; do
choice=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --default-item "${lora_usePreset^}" --item-help --menu "Presets are pre-defined modem settings (Bandwidth, Spread Factor, and Coding Rate) which influence both message speed and range. The vast majority of users use a preset.\n\nUse modem preset? (current: ${lora_usePreset:-unknown})" 0 0 0 \
"True" "(default)" "" \
"False" "" "" \
" " "" "" \
"$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" "" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] || [ "$choice" == "Cancel" ] || [ "$choice" == "Skip" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
[ "$choice" == "" ] && continue #restart loop if no choice made
using_preset=$choice
command+="--set lora.use_preset $(echo "$choice" | tr '[:upper:]' '[:lower:]') "
break
done
fi
if [ "$1" = "wizard" ] && [ "$using_preset" = "False" ]; then
dialog --no-collapse --title "$title" --colors --msgbox "Not using preset, so skipping Preset setting." 6 50
else
if [ "$1" = "preset" ] || [ "$1" = "wizard" ]; then
options=("LONG_FAST" "LONG_SLOW" "VERY_LONG_SLOW" "MEDIUM_SLOW" "MEDIUM_FAST" "SHORT_SLOW" "SHORT_FAST" "SHORT_TURBO")
menu_items=()
# Create menu options from the array
for i in "${!options[@]}"; do
if [ $i -eq 0 ]; then
menu_items+=("${options[$i]}" "(default)" "") # First item with "(default)"
else
menu_items+=("${options[$i]}" "" "") # Other items without "(default)"
fi
done
menu_items+=("" "" "" "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" "" "")
while true; do
choice=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --default-item "${lora_modemPreset^}" --item-help --menu "The default preset will provide a strong mixture of speed and range, for most users.\n\nPreset? (current: ${lora_modemPreset:-unknown})" 0 0 0 \
"${menu_items[@]}" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] || [ "$choice" == "Cancel" ] || [ "$choice" == "Skip" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
[ "$choice" == "" ] && continue # Restart loop if no choice made
command+="--set lora.modem_preset $choice "
break
done
fi
fi
if [ "$1" = "wizard" ] && [ "$using_preset" = "True" ]; then
dialog --no-collapse --title "$title" --colors --msgbox "Using preset, so skipping Bandwidth, Spread Factor and Coding Rate settings." 7 50
else
if [ "$1" = "bandwidth" ] || [ "$1" = "wizard" ]; then
while true; do
choice=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --item-help --default-item $lora_bandwidth --menu "Width of the frequency \"band\" used around the calculated center frequency. Only used if modem preset is disabled.\n\nBandwidth? (current: ${lora_bandwidth:-unknown})" 0 0 0 \
0 "(default, automatic)" "" \
31 "" "" \
62 "" "" \
125 "" "" \
250 "" "" \
500 "" "" \
" " "" "" \
"$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" "" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] || [ "$choice" == "Cancel" ] || [ "$choice" == "Skip" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
[ "$choice" == "" ] && continue # Restart loop if no choice made
command+="--set lora.bandwidth $choice "
break
done
fi
if [ "$1" = "spread_factor" ] || [ "$1" = "wizard" ]; then
while true; do
choice=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --item-help --default-item $lora_spreadFactor --menu "Indicates the number of chirps per symbol. Only used if modem preset is disabled.\n\nSpread factor? (current: ${lora_spreadFactor:-unknown})" 0 0 0 \
0 "(default, automatic)" "" \
7 "" "" \
8 "" "" \
9 "" "" \
10 "" "" \
11 "" "" \
12 "" "" \
" " "" "" \
"$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" "" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] || [ "$choice" == "Cancel" ] || [ "$choice" == "Skip" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
[ "$choice" == "" ] && continue # Restart loop if no choice made
command+="--set lora.spread_factor $choice "
break
done
fi
if [ "$1" = "coding_rate" ] || [ "$1" = "wizard" ]; then
while true; do
choice=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --item-help --default-item $lora_codingRate --menu "The proportion of each LoRa transmission that contains actual data - the rest is used for error correction.\n\nCoding rate (only used if modem preset is disabled)? (current: ${lora_codingRate:-unknown})" 0 0 0 \
0 "(default, automatic)" "" \
5 "" "" \
6 "" "" \
7 "" "" \
8 "" "" \
" " "" "" \
"$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" "" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] || [ "$choice" == "Cancel" ] || [ "$choice" == "Skip" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
[ "$choice" == "" ] && continue # Restart loop if no choice made
command+="--set lora.coding_rate $choice "
break
done
fi
fi
if [ "$1" = "frequency_offset" ] || [ "$1" = "wizard" ]; then
while true; do
input=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --inputbox "This parameter is for advanced users with advanced test equipment.\n\nFrequency offset (default: 0)" 0 0 ${lora_frequencyOffset:-unknown} 3>&1 1>&2 2>&3)
[[ -z $input || ($input =~ ^([0-9]{1,6})(\.[0-9]+)?$ && $(echo "$input <= 1000000" | bc -l) -eq 1) ]] && break # exit loop if user input a number between 0 and 1000000. Decimals allowed
dialog --no-collapse --title "$title" --msgbox "Must be between 0-1000000. Decimals allowed." 6 50
done
if [ $? -ne 1 ] && [ -n "$input" ]; then
command+="--set lora.frequency_offset $input "
fi
fi
if [ "$1" = "hop_limit" ] || [ "$1" = "wizard" ]; then
while true; do
input=$(dialog --no-collapse --colors --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --inputbox "The maximum number of intermediate nodes between Femtofox and a node it is sending to. Does not impact received messages.\n\n\Z1WARNING:\Zn Excessive hop limit increases congestion!\n\nHop limit. Must be 0-7 (default: 3)" 0 0 ${lora_hopLimit:-unknown} 3>&1 1>&2 2>&3)
[[ -z $input || ($input =~ ^[0-7]$) ]] && break # exit loop if user input an integer between 0 and 7
dialog --no-collapse --title "$title" --msgbox "Must be an integer between 0 and 7." 6 50
done
if [ $? -ne 1 ] && [ -n "$input" ]; then
command+="--set lora.hop_limit $input "
fi
fi
if [ "$1" = "tx_enabled" ] || [ "$1" = "wizard" ]; then
choice="" # zero the choice before loading the submenu
while true; do
choice=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --default-item "${lora_txEnabled^}" --item-help --menu "Enables/disables the radio chip. Useful for hot-swapping antennas.\n\nEnable TX? (current: ${lora_txEnabled:-unknown})" 0 0 0 \
"True" "(default)" "" \
"False" "" "" \
" " "" "" \
"$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" "" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] || [ "$choice" == "Cancel" ] || [ "$choice" == "Skip" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
[ "$choice" == "" ] && continue #restart loop if no choice made
command+="--set lora.tx_enabled $(echo "$choice" | tr '[:upper:]' '[:lower:]') "
break
done
fi
if [ "$1" = "tx_power" ] || [ "$1" = "wizard" ]; then
while true; do
input=$(dialog --no-collapse --colors --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --inputbox "\
\Z1\ZuWARNING!\Zn\n\
Setting a 33db radio above 8db will \Zupermanently\Zn damage it.\n\
ERP above 27db violates EU law.\n\
ERP above 36db violates US (unlicensed) law.\n\
\n\
If 0, will use the maximum continuous power legal in your region.
\n\
\n\
TX power in dBm. Must be 0-30 (0 for automatic)" 0 0 ${lora_txPower:-unknown} 3>&1 1>&2 2>&3)
[[ -z $input || $input =~ ^([12]?[0-9]|30)$ ]] && break # exit loop if user input an integer between 0 and 30
dialog --no-collapse --title "$title" --msgbox "Must be an integer between 0 and 30." 6 50
done
if [ $? -ne 1 ] && [ -n "$input" ]; then
command+="--set lora.tx_power $input "
fi
fi
if [ "$1" = "frequency_slot" ] || [ "$1" = "wizard" ]; then
while true; do
input=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --inputbox "Determines the exact frequency the radio transmits and receives. If unset or set to 0, determined automatically by the primary channel name.\n\nFrequency slot (0 for automatic)" 0 0 ${lora_channelNum:-unknown} 3>&1 1>&2 2>&3)
[[ -z $input || ($input =~ ^[0-9]+$) ]] && break # exit loop if user input an integer 0 or higher
dialog --no-collapse --title "$title" --msgbox "Must be an integer 0 or higher." 6 50
done
if [ $? -ne 1 ] && [ -n "$input" ]; then
command+="--set lora.channel_num $input "
fi
fi
if [ "$1" = "override_duty_cycle" ] || [ "$1" = "wizard" ]; then
while true; do
choice=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --default-item "$(echo "${lora_overrideDutyCycle:-False}" | sed 's/^./\U&/')" --item-help --menu "May have legal ramifications.\n\nOverride duty cycle? (current: ${lora_overrideDutyCycle:-unknown})" 0 0 0 \
"True" "" "" \
"False" "(default)" "" \
" " "" "" \
"$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" "" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] || [ "$choice" == "Cancel" ] || [ "$choice" == "Skip" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
[ "$choice" == "" ] && continue #restart loop if no choice made
command+="--set lora.override_duty_cycle $(echo "$choice" | tr '[:upper:]' '[:lower:]') "
break
done
fi
if [ "$1" = "sx126x_rx_boosted_gain" ] || [ "$1" = "wizard" ]; then
while true; do
choice=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --default-item "$(echo "${lora_sx126xRxBoostedGain:-True}" | sed 's/^./\U&/')" --item-help --menu "This is an option specific to the SX126x chip series which allows the chip to consume a small amount of additional power to increase RX (receive) sensitivity.\n\nEnable SX126X RX boosted gain? (current: ${lora_sx126xRxBoostedGain:-unknown})" 0 0 0 \
"True" "(default)" "" \
"False" "" "" \
" " "" "" \
"$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" "" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] || [ "$choice" == "Cancel" ] || [ "$choice" == "Skip" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
[ "$choice" == "" ] && continue #restart loop if no choice made
command+="--set lora.sx126x_rx_boosted_gain $(echo "$choice" | tr '[:upper:]' '[:lower:]') "
break
done
fi
if [ "$1" = "override_frequency" ] || [ "$1" = "wizard" ]; then
while true; do
input=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --inputbox "Overrides frequency slot. May have legal ramifications.\n\nOverride frequency in MHz (0 for none)." 0 0 ${lora_overrideFrequency:-unknown} 3>&1 1>&2 2>&3)
[[ -z $input || ($input =~ ^[0-9]+(\.[0-9]+)?$) ]] && break # exit loop if user input a number 0 or higher (decimals allowed)
dialog --no-collapse --title "$title" --msgbox "Must be a number 0 or higher. Decimals allowed." 6 53
done
if [ $? -ne 1 ] && [ -n "$input" ]; then
command+="--set lora.override_frequency $input "
fi
fi
if [ "$1" = "ignore_mqtt" ] || [ "$1" = "wizard" ]; then
while true; do
choice=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --default-item "$(echo "${lora_ignoreMqtt:-unknown}" | sed 's/^./\U&/')" --item-help --menu "Ignores any messages it receives via LoRa that came via MQTT somewhere along the path towards the device.\n\nIgnore MQTT? (current: ${lora_ignoreMqtt:-unknown})" 0 0 0 \
"True" "" "" \
"False" "(default)" "" \
" " "" "" \
"$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" "" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] || [ "$choice" == "Cancel" ] || [ "$choice" == "Skip" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
[ "$choice" == "" ] && continue #restart loop if no choice made
command+="--set lora.ignore_mqtt $(echo "$choice" | tr '[:upper:]' '[:lower:]') "
break
done
fi
if [ "$1" = "ok_to_mqtt" ] || [ "$1" = "wizard" ]; then
while true; do
choice=$(dialog --no-collapse --title "$title" --cancel-label "$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" --default-item "$(echo "${lora_configOkToMqtt:-unknown}" | sed 's/^./\U&/')" --item-help --menu "Indicates that the user approves their packets to be uplinked to MQTT brokers.\n\nOK to MQTT? (current: ${lora_configOkToMqtt:-unknown})" 0 0 0 \
"True" "" "" \
"False" "(default)" "" \
" " "" "" \
"$([[ "$1" == "wizard" ]] && echo "Skip" || echo "Cancel")" "" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] || [ "$choice" == "Cancel" ] || [ "$choice" == "Skip" ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
[ "$choice" == "" ] && continue #restart loop if no choice made
command+="--set lora.config_ok_to_mqtt $(echo "$choice" | tr '[:upper:]' '[:lower:]') "
break
done
fi
send_settings $1
fi
}
# Parse options
help="If script is run without arguments, menu will load.\n\
Options are:\n\
-h This message\n\
-w Wizard mode (skips main menu)\
"
while getopts ":hw" opt; do
case ${opt} in
h) # Option -h (help)
echo -e $help
;;
w) # Option -w (Wizard mode)
lora_settings_actions "wizard"
;;
\?) # Unknown option)
echo -e "Unknown argument $1.\n$help"
;;
esac
done
[ -n "$1" ] && exit # if there were arguments, exit before loading the menu
command="" # initialize command
LoRa_menu_choice="" # zero the choice before loading the submenu
while true; do
command="" # initialize command
LoRa_menu_choice=$(dialog --no-collapse --title "Meshtastic LoRa Settings" --default-item "$LoRa_menu_choice" --cancel-label "Back" --item-help --menu "Select a LoRa setting or run the wizard" 30 50 20 \
1 "Wizard (set all)" "" \
2 "Set LoRa radio model" "" \
3 "Configure automatically with URL" "" \
4 "Region" "" \
5 "Use modem preset" "" \
6 "Preset" "" \
7 "Bandwidth" "" \
8 "Spread factor" "" \
9 "Coding rate" "" \
10 "Frequency offset" "" \
11 "Hop limit" "" \
12 "Enable/disable TX" "" \
13 "TX power" "" \
14 "Frequency slot" "" \
15 "Override duty cycle" "" \
16 "SX126X RX boosted gain " "" \
17 "Override frequency" "" \
18 "Ignore MQTT" "" \
19 "OK to MQTT" "" \
" " "" "" \
20 "Back to Meshtastic Menu" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $LoRa_menu_choice in
1) # Wizard (set all)
lora_settings_actions "wizard"
;;
2) # Set LoRa radio model)
lora_settings_actions "set_lora_radio_model"
;;
3) # Configure automatically with URL)
config_url
;;
4) # Region)
lora_settings_actions "region"
;;
5) # Use modem preset)
lora_settings_actions "use_modem_preset"
;;
6) # Preset)
lora_settings_actions "preset"
;;
7) # Bandwidth)
lora_settings_actions "bandwidth"
;;
8) # Spread factor)
lora_settings_actions "spread_factor"
;;
9) # Coding rate)
lora_settings_actions "coding_rate"
;;
10) # Frequency offset)
lora_settings_actions "frequency_offset"
;;
11) # Hop limit)
lora_settings_actions "hop_limit"
;;
12) # Enable/disable TX)
lora_settings_actions "tx_enabled"
;;
13) # TX power)
lora_settings_actions "tx_power"
;;
14) # Frequency slot)
lora_settings_actions "frequency_slot"
;;
15) # Override duty cycle)
lora_settings_actions "override_duty_cycle"
;;
16) # SX126X RX boosted gain)
lora_settings_actions "sx126x_rx_boosted_gain"
;;
17) # Override frequency)
lora_settings_actions "override_frequency"
;;
18) # Ignore MQTT)
lora_settings_actions "ignore_mqtt"
;;
19) # OK to MQTT)
lora_settings_actions "ok_to_mqtt"
;;
20) break ;;
esac
done

View file

@ -55,10 +55,10 @@ while getopts ":hx:Ts:p:c:eiwn:tr" opt; do
T) # Option -T (toggle wifi state)
if [ "$(cat /etc/wifi_state.txt)" == "up" ]; then
logger "Toggling wifi off"
femto-network-config.sh -x "up"
femto-network-config.sh -x "down"
else
logger "Toggling wifi on"
femto-network-config.sh -x "down"
femto-network-config.sh -x "up"
fi
;;
s) # Option -s (ssid)
@ -103,7 +103,7 @@ MAC address:$(ifconfig wlan0 | grep ether | awk '{print $2}')"
Wi-Fi status:\033[4m\033[0;34menabled\033[0m\n\
Connected to:$(iwconfig 2>/dev/null | grep -i 'ESSID' | awk -F 'ESSID:"' '{print $2}' | awk -F '"' '{print $1}' | sed 's/^$/none/')\n\
Sig. strength:$(iwconfig 2>/dev/null | grep -i 'Signal level' | awk -F 'Signal level=' '{print $2}' | awk '{print $1}')\n\
Current IP:$(hostname -I | awk '{print $1}')\n
Current IP:$(ip addr show wlan0 | grep 'inet ' | awk '{print $2}' | cut -d/ -f1)\n
Hostname:$(hostname).local\n\
$mac_address_line"
else
@ -147,18 +147,19 @@ $wifi_settings"
updated_wifi="true"
;;
n) # Option -n (set hostname)
old_hostname=$(hostname)
sed -i "s/$(hostname)/$OPTARG/g" /etc/hosts
hostnamectl set-hostname "$OPTARG"
systemctl restart avahi-daemon
echo "Regenerating web terminal ssl keys..."
femto-utils.sh -T
[ "$OPTARG" != "$old_hostname" ] && /usr/local/bin/packages/ttyd.sh -k
;;
\?) # Invalid option
\?) # Invalid option)
echo "Invalid option: -$OPTARG"
echo -e "$help"
exit 1
;;
:) # Missing argument for option
:) # Missing argument for option)
echo "Option -$OPTARG requires a setting."
echo -e "$help"
exit 1

View file

@ -60,58 +60,58 @@ KILL: add PWR switch or thermal cutoff/fuse & remove resistor."
femtofox_zero="\
┌────┐ ┌────┐
│⚪ \ / ⚪│
│ \ / │
│ └─────────┘ │
│ ┌─────────────────┐ │
│ ●│● USB-C ●│● │
│ ●│● ●│● │
│ ●│● ●│● │
│ ●│● LUCKFOX ●│● │
│ ●│● PICO MINI ●│● │
│ ●│● ●│● │
│ ●│● FOXHOLE ●│● │
│ ●│● ●│● │
│ ●│● ●│● │
│ ●│● ●│● │
│ ●│● ●│● │
│ └────●─●─●─●─●────┘ │
├───┐ ┌─────────────┐ ┌───┤
GND │ ● │ │ HT-RA62 │ │ ● │ GND
3V3 │ ● │ │ ┌───────┐ │ │ ● │ 3V3
UART4-RX │ ● │ │ │ │ │ │ ● │ I2C SDA
UART4-TX │ ● │ │ │ WIO │ │ │ ● │ I2C SCL
├───┘ │ │SX 1262│ │ └───┤
│ │ └───────┘ │ ● │ UNUSED
│ └─────────────┘ ● │ GND
│⚪ ETH ⚪│
└────────●─●─●─●─●────────┘
R R G T T
X X N X X
- + D - + \n"
┌────┐ ┌────┐ \n\
│⚪ \ / ⚪│ \n\
│ \ / │ \n\
│ └─────────┘ │ \n\
│ ┌─────────────────┐ │ \n\
│ ●│● USB-C ●│● │ \n\
│ ●│● ●│● │ \n\
│ ●│● ●│● │ \n\
│ ●│● LUCKFOX ●│● │ \n\
│ ●│● PICO MINI ●│● │ \n\
│ ●│● ●│● │ \n\
│ ●│● FOXHOLE ●│● │ \n\
│ ●│● ●│● │ \n\
│ ●│● ●│● │ \n\
│ ●│● ●│● │ \n\
│ ●│● ●│● │ \n\
│ └────●─●─●─●─●────┘ │ \n\
├───┐ ┌─────────────┐ ┌───┤ \n\
GND │ ● │ │ HT-RA62 │ │ ● │ GND \n\
3V3 │ ● │ │ ┌───────┐ │ │ ● │ 3V3 \n\
UART4-RX │ ● │ │ │ │ │ │ ● │ I2C SDA \n\
UART4-TX │ ● │ │ │ WIO │ │ │ ● │ I2C SCL \n\
├───┘ │ │SX 1262│ │ └───┤ \n\
│ │ └───────┘ │ ● │ UNUSED \n\
│ └─────────────┘ ● │ GND \n\
│⚪ ETH ⚪│ \n\
└────────●─●─●─●─●────────┘ \n\
R R G T T \n\
X X N X X \n\
- + D - + "
femtofox_tiny="coming soon"
luckfox="\
┌────┬───────┬────┐
VBUS 3.3-5V ●│● │ USB-C │ ●│● 1V8 OUT
GND ●│● │ │ ●│● GND
3V3 IN/OUT ●│● └───────┘ ●│● 145, SARADC-IN1 1.8V
UART2-TX DEBUG, 42 ●│● ●│● 144, SARADC-IN0 1.8V
UART2-RX DEBUG, 43 ●│● [BTN] ●│● 4
CS0, 48 ●│● ●│● 55, IRQ
CLK, 49 ●│● ●│● 54, BUSY
MOSI, 50 ●│● ●│● 59, I2C SCL
MISO, 51 ●│● ●│● 58, I2C SDA
UART4-RX, 52 ●│● ●│● 57, NRST, UART3-RX
UART4-TX, 53 ●│● ETH ●│● 56, RXEN, UART3-TX
└──●──●──●──●──●──┘
R R G T T
X X N X X
- + D - +
GPIO BANK 0 (3.3v): 4
GPIO BANK 1 (3.3v): 42 43 48 49 50 51 52 53 54 55 56 57 58 59
┌────┬───────┬────┐ \n\
VBUS 3.3-5V ●│● │ USB-C │ ●│● 1V8 OUT \n\
GND ●│● │ │ ●│● GND \n\
3V3 IN/OUT ●│● └───────┘ ●│● 145, SARADC-IN1 1.8V\n\
UART2-TX DEBUG, 42 ●│● ●│● 144, SARADC-IN0 1.8V\n\
UART2-RX DEBUG, 43 ●│● [BTN] ●│● 4 \n\
CS0, 48 ●│● ●│● 55, IRQ \n\
CLK, 49 ●│● ●│● 54, BUSY \n\
MOSI, 50 ●│● ●│● 59, I2C SCL \n\
MISO, 51 ●│● ●│● 58, I2C SDA \n\
UART4-RX, 52 ●│● ●│● 57, NRST, UART3-RX \n\
UART4-TX, 53 ●│● ETH ●│● 56, RXEN, UART3-TX \n\
└──●──●──●──●──●──┘ \n\
R R G T T \n\
X X N X X \n\
- + D - + \n\
GPIO BANK 0 (3.3v): 4 \n\
GPIO BANK 1 (3.3v): 42 43 48 49 50 51 52 53 54 55 56 57 58 59\n\
GPIO BANK 4 (1.8v): 144 145 "
# Parse options

View file

@ -3,7 +3,8 @@ log_message() {
echo -e "\e[32mFirst boot\e[0m: $1" # Echo to the screen
logger "First boot: $1" # Log to the system log
}
if ! grep -qE '^first_boot=true' /etc/femto.conf; then # if not the first boot
if ! systemctl is-enabled femto-runonce &>/dev/null; then # if not the first boot
who | grep -q . || exit 0 # if not logged in, exit script. May not deal well with future web UI
@ -18,14 +19,18 @@ Re-running this script will:\n\
* Resize filesystem to fit the SD card\n\
* Allocate the swap file\n\
* Replace the SSH encryption keys\n\
* Add terminal type to user femto's .bashrc\n\
* Replace the Web Terminal SSL encryption keys\n\
* Set the eth0 MAC to be derivative of CPU serial number\n\
* Add terminal type to user femto's .bashrc\n\
* Add a shortcut \`sfc\` to user femto's .bashrc\n\
* Enable the meshtasticd service\n\
* Add compiler support\n\
\n\
Finally, the Femtofox will reboot.\n\
\n\
Re-running this script after first boot should not cause any harm, but may not work as expected.\n\
\n\
Proceed?" 19 60
Proceed?" 24 60
if [ $? -eq 1 ]; then #if cancel/no
exit 0
fi
@ -44,15 +49,15 @@ echo -e "\e[32m******* First boot *******\e[0m"
) &
# Perform filesystem resize
log_message "Resizing filesystem. This can take several minutes, depending on microSD card size and speed"
log_message "Resizing filesystem..."
resize2fs /dev/mmcblk1p5
resize2fs /dev/mmcblk1p6
resize2fs /dev/mmcblk1p7
log_message "Resizing filesystem complete"
log_message "Resizing filesystem complete."
# allocate swap file
if [ ! -f /swapfile ]; then # check if swap file already exists
log_message "Allocating swap file. This can take up to 10 minutes, depending on microSD card speed"
log_message "Allocating swap file..."
fallocate -l 1G /swapfile
chmod 600 /swapfile
mkswap /swapfile > /dev/null
@ -60,29 +65,21 @@ if [ ! -f /swapfile ]; then # check if swap file already exists
echo '/swapfile none swap sw 0 0' | tee -a /etc/fstab > /dev/null
log_message "Swap file allocated."
else
log_message "Swap file already allocated, skipping"
log_message "Swap file already allocated, skipping..."
fi
#generate SSH keys
log_message "Generating new SSH encryption keys. This can take a minute..."
femto-utils.sh -E
#generate ttyd SSL keys
log_message "Generating new Web Terminal SSL encryption keys. This can take a minute..."
femto-utils.sh -T
# prevent randomized mac address for eth0. If `eth0`` is already present in /etc/network/interfaces, skip
mac="$(awk '/Serial/ {print $3}' /proc/cpuinfo | tail -c 11 | sed 's/^\(.*\)/a2\1/' | sed 's/\(..\)/\1:/g;s/:$//')"
if ! grep -q "eth0" /etc/network/interfaces; then
log_message "Setting eth0 MAC address to $mac (derivative of CPU s/n)"
cat <<EOF >> /etc/network/interfaces
# static mac address for onboard ethernet (castellated pins)
allow-hotplug eth0
iface eth0 inet dhcp
hwaddress ether $mac
EOF
file="/etc/network/interfaces"
if ! grep -q " hwaddress ether $mac" "$file"; then
log_message "Setting eth0 MAC address to $mac (derivative of CPU s/n)..."
awk -v mac="$mac" '
{ print }
/allow-hotplug eth0/ { count=5 }
count && --count == 0 { print " hwaddress ether " mac }
' "$file" > "$file.tmp" && mv "$file.tmp" "$file"
else
log_message "eth0 already exists in /etc/network/interfaces, skipping"
log_message "eth0 mac address already set in /etc/network/interfaces, skipping..."
fi
# Add term stuff to .bashrc
@ -90,14 +87,39 @@ lines="export NCURSES_NO_UTF8_ACS=1
export TERM=xterm-256color
export LANG=C.UTF-8"
if ! grep -Fxq "$lines" /home/femto/.bashrc; then # Check if the lines are already in .bashrc
log_message "Adding TERM, LANG and NCURSES_NO_UTF8_ACS to .bashrc..."
echo "$lines" >> /home/femto/.bashrc
echo "Added TERM, LANG and NCURSES_NO_UTF8_ACS to .bashrc"
else
echo "TERM, LANG and NCURSES_NO_UTF8_ACS already present in .bashrc, skipping"
log_message "TERM, LANG and NCURSES_NO_UTF8_ACS already present in .bashrc, skipping..."
fi
# Fix Compiler
log_message "Adding compiler support..."
cp /usr/lib/arm-linux-gnueabihf/libc_nonshared.a.keep /usr/lib/arm-linux-gnueabihf/libc_nonshared.a
# Add a cheeky alias to .bash_aliases
if ! grep -Fxq "alias sfc='sudo femto-config'" /home/femto/.bashrc; then # Check if the lines are already in .bash_aliases
echo "alias sfc='sudo femto-config'" >> /home/femto/.bashrc
log_message "Added \`alias sfc='sudo femto-config'\` to .bashrc"
else
log_message "\`alias sfc='sudo femto-config'\` already present in .bashrc, skipping..."
fi
log_message "Enabling meshtasticd service..."
systemctl enable meshtasticd
#generate SSH keys
log_message "Generating new SSH encryption keys. This can take a few minutes..."
femto-utils.sh -E
#generate ttyd SSL keys
log_message "Generating new Web Terminal (ttyd) SSL encryption keys. This can take a few minutes..."
/usr/local/bin/packages/ttyd.sh -k
log_message "Enabling Web Terminal (ttyd) service..."
systemctl enable ttyd
# remove first boot flag
sed -i -E 's/^first_boot=.*/first_boot=false/' /etc/femto.conf
log_message "Removing first boot flag and rebooting in 5 seconds..."
systemctl disable femto-runonce
log_message "Disabled first boot service and rebooting in 5 seconds..."
sleep 5
reboot
reboot

View file

@ -19,19 +19,23 @@ If no argument is specified, a menu system will be used. Options are:
EOF
)
log_message() {
logger $1
if [ $arg_count -eq 0 ]; then
dialog --msgbox "$1" 12 50
else
echo -e $1
fi
}
set_timezone() {
echo "Setting time zone..."
ln -f -s /usr/share/zoneinfo/$1 /etc/localtime >/dev/null 2>&1
dpkg-reconfigure --frontend noninteractive tzdata >/dev/null 2>&1
if [ ! -f /usr/share/zoneinfo/$1 >/dev/null 2>&1 ]; then
echo -e "Invalid timezone: $1"
return 1
fi
desired_offset=$(TZ=$1 date +"%:z")
current_offset=$(date +"%:z")
if [ "$desired_offset" != "$current_offset" ]; then
echo -e "FAILED to set timezone to $1. Expected GMT offset: $desired_offset, but got: $current_offset"
return 1
else
echo "Set timezone to $current_offset"
return 0
fi
}
set_timestamp() {
@ -41,7 +45,7 @@ for i in {1..5}; do
echo "Time Zone updated to:\n$(timedatectl show --property=Timezone --value) $(date +%Z) (UTC$(date +%:z))\nSystem time updated to:\n$(date)\n\nNew time successfully saved to RTC.\nTime & date are also set automatically from internet, if connected."
return 0
else
echo "System time updated to:\n$(date) ($(date +"UTC%z" | sed -E 's/GMT([+-])0?([0-9]{1,2})00/GMT\1\2/'))\n\nUnable to communicate with RTC module. An RTC module can remember system time between reboots/power outages.\nTime & date are also set automatically from internet, if connected."
echo "System time updated to:\n$(date +"%B %d, %Y %H:%M:%S") $(timedatectl show --property=Timezone --value) ($(date +"UTC%z" | sed -E 's/GMT([+-])0?([0-9]{1,2})00/GMT\1\2/'))\n\nUnable to communicate with RTC module. An RTC module can remember system time between reboots/power outages.\nTime & date are also set automatically from internet, if connected."
return 0
fi
fi
@ -55,9 +59,11 @@ while getopts ":t:T:h" opt; do
case ${opt} in
t) # Option -t (timezone)
set_timezone "$OPTARG"
[ $? -eq 1 ] && exit 1
;;
T) # Option -t (timestamp)
set_timestamp "$OPTARG"
[ $? -eq 1 ] && exit 1 || exit 0
;;
h) # Option -h (help)
echo -e "$help"
@ -68,7 +74,12 @@ done
if [ $arg_count -eq 0 ]; then # if the script was launched with no arguments, then load the UI.
echo "Loading current time settings..."
current_timezone=$(timedatectl show --property=Timezone --value)
dialog --no-collapse --title "$title" --yesno "Current system time: $(date +"%H:%M:%S")\nCurrent time zone: $current_timezone ($(date +"UTC%z" | sed -E 's/GMT([+-])0?([0-9]{1,2})00/GMT\1\2/'))\n$(hwclock >/dev/null 2>&1 && echo "RTC module found!" || echo "RTC module not found.")\n\nSet new time and timezone?" 10 60
dialog --no-collapse --title "System time" --yesno "\
Current system time:\n\
$(date +"%B %d, %Y %H:%M:%S") $(timedatectl show --property=Timezone --value) ($(date +"UTC%z" | sed -E 's/GMT([+-])0?([0-9]{1,2})00/GMT\1\2/'))\n\
$(hwclock >/dev/null 2>&1 && echo "RTC module found!" || echo "RTC module not found.")\n\
\n\
Set new time and timezone?" 10 50
if [ $? -eq 1 ]; then #unless cancel/no
exit 0
fi
@ -85,9 +96,9 @@ if [ $arg_count -eq 0 ]; then # if the script was launched with no arguments, th
options_str=$(printf '%s\n' "${options[@]}")
# Show timezone selection menu with preselection of current timezone
selected_timezone=$(dialog --title "Select Time Zone" \
selected_timezone=$(dialog --title "Set Time Zone" \
--default-item "$current_timezone" \
--menu "Current time zone: $current_timezone (UTC$(date +%z))" 20 60 10 \
--menu "Current time zone: $current_timezone (UTC$(date +%z))" 20 50 10 \
$(printf "%s " "${options[@]}") 3>&1 1>&2 2>&3)
exit_status=$?
if [[ $exit_status -eq 0 && -n "$selected_timezone" ]]; then
@ -97,7 +108,7 @@ if [ $arg_count -eq 0 ]; then # if the script was launched with no arguments, th
exit 1
fi
DATE=$(dialog --title "Select Date" --calendar "Current date: $(date "+%B %d, %Y") \nPress [TAB] to select." 0 0 $(date +%d) $(date +%m) $(date +%Y) 3>&1 1>&2 2>&3)
DATE=$(dialog --title "Set Date" --calendar "Current date: $(date "+%B %d, %Y") \nPress [TAB] to select." 0 0 $(date +%d) $(date +%m) $(date +%Y) 3>&1 1>&2 2>&3)
if [ $? -ne 0 ]; then
exit 1
fi
@ -106,7 +117,16 @@ if [ $arg_count -eq 0 ]; then # if the script was launched with no arguments, th
if [ $? -eq 1 ]; then #if cancel/no
exit 1
fi
log_message "$(set_timestamp $(date -d "$DATE $TIME" +%s))"
exit $? #exit status matches set_timestamp exit status
msg="$(set_timestamp $(date -d "$DATE $TIME" +%s))"
exit_status=$?
logger $msg
if [ $arg_count -eq 0 ]; then
dialog --msgbox "$msg" 13 50
else
echo -e $msg
fi
exit $exit_status #exit status matches set_timestamp exit status
fi

View file

@ -4,16 +4,26 @@ title="Software Manager"
package_dir="/usr/local/bin/packages"
install() {
dialog --no-collapse --title "Install $($package_dir/$1.sh -N)" --yesno "\nInstallation requires internet connectivity.\n\nProceed?" 10 40
dialog --no-collapse --title "Install $($package_dir/$1.sh -N)" --yesno "\nInstallation requires internet connectivity.\n\nInstall $($package_dir/$1.sh -N)?" 10 40
[ $? -eq 1 ] && return 1 #if cancel/no
echo "Installing $($package_dir/$1.sh -N)..."
# Run the installation script, capturing the output and displaying it in real time
output=$($package_dir/$1.sh -i)
install_status=$? # Capture the exit status of the eval command
output="$($package_dir/$1.sh -i 2>&1 | tee /dev/tty)"
install_status=$([[ "$output" == *"failed"* ]] && echo 1 || echo 0)
# Capture the exit status of the eval command
if [ ${#output} -gt 2048 ]; then # Truncate to 2048 characters and append ellipsis and note if necessary
truncated_output="${output:0:2000}...\nLOG TRUNCATED"
if [[ "$output" =~ user_message: ]]; then # preserve user_message by adding to end of string
truncated_output="$truncated_output\n$(echo "$output" | sed -n 's/.*\(user_message:.*\)/\1/p')"
fi
output="$truncated_output"
fi
user_message=$(echo "$output" | awk '/user_message: / {found=1; split($0, arr, "user_message: "); print arr[2]; next} found {print}' | sed '/^$/q') # grab the user_message, if present
output=$(echo -e "$output" | sed '/user_message: /,$d') # remove the user message from the detailed output
echo $install_status
if [ $install_status -eq 0 ]; then # if the installation was successful
dialog --no-collapse --colors --title "$title" --beep --msgbox "\ZuInstallation of $($package_dir/$1.sh -N) successful!\Zn$([ -n "$user_message" ] && echo "\n\n$user_message")\n\nLog:\n$(echo $output)" 0 0 # if there's a user_message, display it with two preceeding line breaks
else
@ -22,7 +32,7 @@ install() {
}
uninstall() {
dialog --no-collapse --title "Uninstall $($package_dir/$1.sh -N)" --yesno "\nReinstallation will require internet connectivity.\n\nProceed?" 10 40
dialog --no-collapse --title "Uninstall $($package_dir/$1.sh -N)" --yesno "\nNote: reinstallation will require internet connectivity.\n\nUninstall $($package_dir/$1.sh -N)?" 10 40
[ $? -eq 1 ] && return 1 #if cancel/no
echo "Uninstalling $($package_dir/$1.sh -N)..."
output=$(eval "$package_dir/$1.sh -u 2>&1 | tee /dev/tty")
@ -37,7 +47,7 @@ uninstall() {
}
initialize() {
dialog --no-collapse --title "$title" --yesno "\nIntialize $($package_dir/$1.sh -N)\n\nInitialization runs commands that require user interaction and so can only be run from terminal.\n\nProceed?" 13 50
dialog --no-collapse --title "$title" --yesno "\nIntialize $($package_dir/$1.sh -N)\n\nInitialization runs commands that require user interaction and so can only be run from terminal.\n\nInitialize $($package_dir/$1.sh -N)?" 13 50
[ $? -eq 1 ] && return 1 #if cancel/no
clear
echo "Initializing $($package_dir/$1.sh -N)..."
@ -50,11 +60,11 @@ initialize() {
}
upgrade() {
dialog --no-collapse --title "Upgrade $($package_dir/$1.sh -N)" --yesno "\nUpgrade requires internet connectivity.\n\nProceed?" 10 40
dialog --no-collapse --title "Upgrade $($package_dir/$1.sh -N)" --yesno "\nUpgrade requires internet connectivity.\n\nUpgrade $($package_dir/$1.sh -N)?" 10 40
[ $? -eq 1 ] && return 1 #if cancel/no
echo "Upgrading $($package_dir/$1.sh -N)..."
output=$(eval "$package_dir/$1.sh -g 2>&1 | tee /dev/tty")
install_status=$? # Capture the exit status of the eval command
output="$($package_dir/$1.sh -g 2>&1 | tee /dev/tty)"
install_status=$([[ "$output" == *"failed"* ]] && echo 1 || echo 0)
user_message=$(echo "$output" | awk '/user_message: / {found=1; split($0, arr, "user_message: "); print arr[2]; next} found {print}' | sed '/^$/q') # grab the user_message, if present
output=$(echo "$output" | sed '/user_message: /,$d') # remove the user message from the detailed output
if [ $install_status -eq 0 ]; then # if the installation was successful
@ -69,16 +79,18 @@ upgrade() {
package_intro() {
echo "Loading package info..."
# check if each field in the package info is supported by the package, and if so get it and insert it into the package info dialog
dialog --no-collapse --colors --title "$title" --msgbox "\
$($package_dir/$1.sh -N)\n\
$(if $package_dir/$1.sh -O | grep -q 'A'; then echo -e "by $($package_dir/$1.sh -A)"; fi)\n\
dialog --no-collapse --colors --title "$title" --yes-label "Continue" --no-label "Back" --yesno "\
$($package_dir/$1.sh -N)\n\
$(if $package_dir/$1.sh -O | grep -q 'A'; then echo -e "by $($package_dir/$1.sh -A)"; fi)\n\
$(if $package_dir/$1.sh -O | grep -q 'D'; then echo "\n$($package_dir/$1.sh -D)"; fi)\n\
\n\
$(echo "Currently: " && $package_dir/$1.sh -I && echo "\Zuinstalled\Zn" || echo "\Zunot installed\Zn")\n\
$([ -n "$($package_dir/$1.sh -E)" ] && $package_dir/$1.sh -I && echo "Service status: \Zu$(femto-utils.sh -C "$($package_dir/$1.sh -E)" | sed 's/\x1b\[[0-9;]*m//g')\Zn\n")\
$(if output=$($package_dir/$1.sh -L); [ -n "$output" ]; then echo "Installs to: \Zu$output\Zn\n"; fi)\
$(if output=$($package_dir/$1.sh -C); [ -n "$output" ]; then echo "Conflicts with: \Zu$output\Zn\n"; fi)\
An internet connection is required for installation.\n\
$(if $package_dir/$1.sh -O | grep -q 'U'; then echo "\nFor more information, visit $($package_dir/$1.sh -U)"; fi)" 0 0
$(if output=$($package_dir/$1.sh -T); [ -n "$output" ]; then echo "License: \Zu$output\Zn\n"; fi)\
$(if $package_dir/$1.sh -O | grep -q 'U'; then echo "Website: \Zu$($package_dir/$1.sh -U)\Zn"; fi)" 0 0
[ $? -eq 1 ] && return 1 # Exit the loop if the user selects "Cancel" or closes the dialog
package_menu $1 # after user hits "OK", move on to package menu
}
@ -86,66 +98,85 @@ package_menu() {
choice=""
while true; do
echo "Loading package menu..."
license_button=""
if $package_dir/$1.sh -O | grep -q 'G' && $package_dir/$1.sh -I; then license_button="--help-button --help-label License"; fi
# for each line, check if it's supported by the package, display it if the current install state of the package is appropriate (example: don't display "install" if the package is already installed, don't display "stop service" for a package with no services)
choice=$(dialog --no-collapse --title "$title" --cancel-label "Back" --default-item "$choice" --menu "$($package_dir/$1.sh -N)" 18 45 5 \
if $package_dir/$1.sh -I; then service_state=$(femto-utils.sh -C "$($package_dir/$1.sh -E)"); fi
# Removed from menu list until can be fixed - contact does not launch. When returned to list, should be first entry
menu_list="\
$(if $package_dir/$1.sh -O | grep -q 'l' && $package_dir/$1.sh -I; then echo "Run software x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'i' && ! $package_dir/$1.sh -I; then echo "Install x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'u' && $package_dir/$1.sh -I; then echo "Uninstall x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'a' && $package_dir/$1.sh -I; then echo "Initialize x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'g' && $package_dir/$1.sh -I; then echo "Upgrade x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I; then echo "Enable service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'd' && $package_dir/$1.sh -I; then echo "Disable service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 's' && $package_dir/$1.sh -I; then echo "Stop service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'r' && $package_dir/$1.sh -I; then echo "Start/restart service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'S' && $package_dir/$1.sh -I; then echo "Get service status x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I && [[ ! $service_state =~ "enabled" ]]; then echo "Enable service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I && [[ ! $service_state =~ "disabled" ]]; then echo "Disable service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I && [[ ! $service_state =~ "not running" ]]; then echo "Stop service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I; then echo "Start/restart service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'S' && $package_dir/$1.sh -I; then echo "Detailed service status x"; fi)"
menu_count=$(( $(echo "$menu_list" | grep -o " x" | wc -l) $(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I; then echo "+1"; fi) )) # count the number of menu items by counting how many times " x" shows up, +1 if there's a service. This is a stupid way to do this, but because each menu item only contains one space (the rest being space-sized invisible chars) it works. It's late at night, OKAY?!
if $package_dir/$1.sh -O | grep -q 'e' && [ "$($package_dir/$1.sh -E | wc -w)" -gt 1 ]; then
multiple_services_note="\nService will appear as \"running\" if any of the services are active."
menu_count=$((menu_count + 2))
fi
choice=$(dialog --no-collapse --colors --title "$($package_dir/$1.sh -N)" $license_button --cancel-label "Back" --default-item "$choice" --menu "$(if $package_dir/$1.sh -O | grep -q 'S' && $package_dir/$1.sh -I; then echo "Service status: $(femto-utils.sh -R "$service_state")"; fi)$multiple_services_note" $(( menu_count + 9 )) 45 $(( menu_count + 3 )) \
$menu_list \
" " "" \
"Back to software manager" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
# execute the actual commands
case $choice in
"Run software") echo "Launching $($package_dir/$1.sh -N)..." && eval "$package_dir/$1.sh -l" ;;
"Install") install $1 ;;
"Uninstall") uninstall $1 ;;
"Initialize") initialize $1 ;;
"Upgrade") upgrade $1 ;;
"Enable service") echo "Enabling and starting service..." && eval "$package_dir/$1.sh -e" && eval "$package_dir/$1.sh -r" ;;
"Disable service") echo "Disabling and stopping service..." && eval "$package_dir/$1.sh -d" && eval "$package_dir/$1.sh -s" ;;
"Stop service") echo "Stopping service..." && eval "$package_dir/$1.sh -s" ;;
"Start/restart service") echo "Starting/restarting service..." && eval "$package_dir/$1.sh -r" ;;
"Get service status") echo "Getting service status..." && dialog --no-collapse --title "$title" --msgbox "$(eval "$package_dir/$1.sh -S")" 0 0 ;;
"Back to software manager") break ;;
esac
exit_status=$? # This line checks the exit status of the dialog command
if [ $exit_status -eq 1 ]; then # Exit the loop if the user selects "Cancel" or closes the dialog
return
elif [ $exit_status -eq 2 ]; then # Help ("extra") button
dialog --no-collapse --colors --title "$($package_dir/$1.sh -N) License" --msgbox " \Zu$($package_dir/$1.sh -N)\Zn\n$(if output=$($package_dir/$1.sh -T); [ -n "$output" ]; then echo "License: $output"; fi)\n\n$($package_dir/$1.sh -G)" 0 0
else
# execute the actual commands
case $choice in
"Run software") eval "$package_dir/$1.sh -l" ;;
"Install") install $1 ;;
"Uninstall") uninstall $1 ;;
"Initialize") initialize $1 ;;
"Upgrade") upgrade $1 ;;
"Enable service") echo "Enabling and starting service..." && eval "$package_dir/$1.sh -e" && eval "$package_dir/$1.sh -r" ;;
"Disable service") echo "Disabling and stopping service..." && eval "$package_dir/$1.sh -d" && eval "$package_dir/$1.sh -s" ;;
"Stop service") echo "Stopping service..." && eval "$package_dir/$1.sh -s" ;;
"Start/restart service") echo "Starting/restarting service..." && eval "$package_dir/$1.sh -r" ;;
"Detailed service status") echo "Getting service status..." && dialog --no-collapse --title "$title" --msgbox "$(eval "$package_dir/$1.sh -S")" 0 0 ;;
"Back to software manager") break ;;
esac
fi
done
}
# generate menu from filenames in /usr/local/bin/packages
while true; do
menu_entries=()
echo "Loading packages..."
menu_entries=("Package name" "Installed?" "" "")
index=1
for file in /usr/local/bin/packages/*.sh; do
filename=$(basename "$file" .sh)
[[ "$filename" == "package_template" ]] && continue # skip package_template.sh
menu_entries+=("$index" "$(/usr/local/bin/packages/"$filename".sh -N)")
((index++))
[[ "$filename" == femto_* ]] && continue # skip filenames starting with femto_
menu_entries+=("$(/usr/local/bin/packages/"$filename".sh -N)" "$($package_dir/$filename.sh -I && echo "✅ " || echo "❌ ")")
((index++)) # keeping an index to determine menu window height
done
menu_entries+=(" " "") # add blank line and "Back to Main Menu" entry
menu_entries+=("$index" "Back to main menu")
software_option=$(dialog --no-collapse --cancel-label "Back" --default-item "$software_option" --menu "$title" $((9 + index)) 50 $((index + 1)) "${menu_entries[@]}" 3>&1 1>&2 2>&3)
menu_entries+=("Back to main menu" "")
software_option=$(dialog --no-collapse --cancel-label "Back" --default-item "$software_option" --menu "$title" $((11 + index)) 50 $((index + 3)) "${menu_entries[@]}" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case_block=" case \$software_option in"
index=1
for file in /usr/local/bin/packages/*.sh; do
filename=$(basename "$file" .sh)
[[ "$filename" == "package_template" ]] && continue # skip package_template.sh
[[ "$filename" == femto_* ]] && continue # skip filenames starting with femto_
case_block+="
$index) package_intro \"$filename\" ;;"
\"$(/usr/local/bin/packages/"$filename".sh -N)\") package_intro \"$filename\" ;;"
((index++))
done
case_block+="
$index) break ;;
\"Back to main menu\") break ;;
esac" #add return to main menu option
eval "$case_block" # Execute the generated case statement
done

View file

@ -14,12 +14,21 @@ log_message() {
echo "$(date +"%Y-%m-%d %H:%M:%S") $1" >> /tmp/femtofox-config.log
}
if grep -qE '^first_boot=true' /etc/femto.conf; then
if systemctl is-enabled femto-runonce &>/dev/null; then
log_message "First boot, skipping USB Configuration Tool."
exit 0
fi
exit_script() {
if [[ -n "$partial_failure" ]]; then
log_message "\033[0;31mPartial failure in usb-config-tool...\033[0m"
for _ in {1..2}; do #boot code
blink "1" && sleep 0.5
done
for _ in {1..2}; do #boot code
blink "0.25" && sleep 0.5
done
fi
if [ ! -z "$usb_path" ]; then #if usb path is populated
if ! df -T /mnt/usb 2>/dev/null | grep -qw 'ntfs'; then
log_message "USB configuration script complete. Copying femtofox-config.log to USB drive."
@ -109,6 +118,8 @@ if [ -f "$mount_point/femtofox-config.txt" ]; then
wifi_command="femto-network-config.sh"
meshtastic_security_command="femto-meshtasticd-config.sh"
dont_run_if_log_exists=""
software_install=""
meshtastic_i2c=""
# Escape and read the fields from the USB config file if they exist
while IFS='=' read -r key value; do
@ -130,8 +141,10 @@ if [ -f "$mount_point/femtofox-config.txt" ]; then
meshtastic_private_key) meshtastic_private_key=$(escape_sed "$value") ;;
meshtastic_admin_key) meshtastic_admin_key=$(escape_sed "$value") ;;
dont_run_if_log_exists) dont_run_if_log_exists=$(escape_sed "$value") ;;
software_install) software_install=$(escape_sed "$value") ;;
meshtastic_i2c) meshtastic_i2c=$(escape_sed "$value") ;;
esac
done < <(grep -E '^(act_led|wifi_ssid|wifi_psk|wifi_country|meshtastic_lora_radio|timezone|meshtastic_url|meshtastic_legacy_admin|meshtastic_public_key|meshtastic_private_key|meshtastic_admin_key|dont_run_if_log_exists)=' "$usb_config")
done < <(grep -E '^(act_led|wifi_ssid|wifi_psk|wifi_country|meshtastic_lora_radio|timezone|meshtastic_url|meshtastic_legacy_admin|meshtastic_public_key|meshtastic_private_key|meshtastic_admin_key|dont_run_if_log_exists|software_install|meshtastic_i2c)=' "$usb_config")
# Check if the log exits and if the dont_run_if_log_exists line is set in the script
if $log_exists && [[ $dont_run_if_log_exists = "true" ]]; then
@ -173,6 +186,13 @@ if [ -f "$mount_point/femtofox-config.txt" ]; then
found_config="true"
update_wifi="true"
fi
if [ "$update_wifi" = true ]; then #if wifi config found, restart wifi
log_message "Making changes to wifi settings and restarting wifi."
wifi_command="$wifi_command -r"
eval $wifi_command 2>&1 | tee -a /tmp/femtofox-config.log
log_message "wpa_supplicant.conf updated and wifi restarted. Enabling Meshtastic wifi setting."
fi
#get meshtastic_lora_radio model, if specified, and copy appropriate yaml to /etc/meshtasticd/config.d/
if [[ -n "$meshtastic_lora_radio" ]]; then
@ -214,12 +234,18 @@ if [ -f "$mount_point/femtofox-config.txt" ]; then
radio="none"
;;
*)
log_message "Invalid LoRa radio name: $meshtastic_lora_radio, ignoring."
log_message "\033[0;31mInvalid LoRa radio name: $meshtastic_lora_radio, ignoring.\033[0m"
partial_failure=true
;;
esac
if [[ -n "$radio" ]]; then # if a radio was found
femto-meshtasticd-config.sh -l "$radio" -s 2>&1 | tee -a /tmp/femtofox-config.log # set the radio and restart the service
log_message "Set LoRa radio to $meshtastic_lora_radio, restarting Meshtasticd."
if [ $? -eq 0 ]; then
log_message "Set LoRa radio to $meshtastic_lora_radio, restarting Meshtasticd."
else
log_message "\033[0;31mSeting LoRa radio to $meshtastic_lora_radio FAILED, restarting Meshtasticd.\033[0m" | tee -a /tmp/femtofox-config.log
partial_failure=true
fi
fi
fi
@ -227,6 +253,10 @@ if [ -f "$mount_point/femtofox-config.txt" ]; then
timezone=$(echo "$timezone" | sed 's/\\//g')
log_message "Updating system timezone to $timezone."
femto-set-time.sh -t "$timezone"
if [ $? -eq 1 ]; then
partial_failure=true
log_message "\033[0;31mSeting timezone to $timezone FAILED.\033[0m" | tee -a /tmp/femtofox-config.log
fi
found_config="true"
fi
@ -270,22 +300,73 @@ if [ -f "$mount_point/femtofox-config.txt" ]; then
meshtastic_security_command+=" -o \"$meshtastic_legacy_admin\"" # add to the command list
fi
if [ "$found_config" = true ]; then #if we found a config file containing valid data
if [ "$update_wifi" = true ]; then #if wifi config found, restart wifi
log_message "Making changes to wifi settings and restarting wifi."
wifi_command="$wifi_command -r"
eval $wifi_command 2>&1 | tee -a /tmp/femtofox-config.log
log_message "wpa_supplicant.conf updated and wifi restarted. Enabling Meshtastic wifi setting."
# get meshtastic_cli= lines and run them
while IFS='=' read -r key value; do
log_message "Meshtastic CLI command found."
femto-meshtasticd-config.sh -m "$value" 3 "Meshtastic CLI command" 2>&1 | tee -a /tmp/femtofox-config.log
if [ $? -eq 1 ]; then
partial_failure=true
log_message "\033[0;31mMeshtastic CLI command \`meshtastic --host $value\` FAILED.\033[0m" | tee -a /tmp/femtofox-config.log
fi
found_config=true
done < <(grep '^meshtastic_cli=' "$usb_config" | sed -E 's/^meshtastic_cli=["]?(.*[^"])["]?$/meshtastic_cli=\1/')
# install software packages from software_install=
package_dir="/usr/local/bin/packages"
export HOME=/root
IFS=',' read -ra packages <<< "$software_install"
for package in "${packages[@]}"; do
if [[ -f "/usr/local/bin/packages/${package}.sh" ]]; then
found_config=true
log_message "Installing $($package_dir/${package}.sh -N) in non-interactive mode..." | tee -a /tmp/femtofox-config.log
for i in {1..5}; do
set -o pipefail
$package_dir/${package}.sh -xi | tee -a /tmp/femtofox-config.log
last_install_attempt_state=${PIPESTATUS[0]}
set +o pipefail
if [ $last_install_attempt_state -eq 0 ]; then
log_message "\033[0;32mInstallation of $($package_dir/${package}.sh -N) successful!\033[0m"
break
fi
[ $i = 5 ] && log_message "Installation failed... Is internet connected?" && break
log_message "Installation failed ($((i+1))/5). Retrying..."
sleep 4
done
if [ $last_install_attempt_state -ne 0 ]; then
log_message "\033[0;31mInstallation of $($package_dir/${package}.sh -N) unsuccessful!\033[0m"
partial_failure=true
fi
else
log_message "\033[0;31mSoftware package $package_dir/${package}.sh does not exist, ignoring...\033[0m"
partial_failure=true
fi
done
if [[ -n "$meshtastic_i2c" ]]; then # set meshtastic i2c state
femto-meshtasticd-config.sh -I $meshtastic_i2c 2>&1 | tee -a /tmp/femtofox-config.log
log_message "Set Meshtastic i2c state to \`$meshtastic_i2c\`."
found_config="true"
fi
if [ "$found_config" = true ]; then #if we found a config file containing valid data
if [ "$meshtastic_url" != "" ]; then
log_message "Connecting to Meshtastic radio and submitting $meshtastic_url"
femto-meshtasticd-config.sh -q "$meshtastic_url" 2>&1 | tee -a /tmp/femtofox-config.log
if [ $? -eq 1 ]; then
partial_failure=true
log_message "\033[0;31mSetting Meshtastic URL to $meshtastic_url FAILED.\033[0m" | tee -a /tmp/femtofox-config.log
fi
fi
if [ "$meshtastic_security_command" != "femto-meshtasticd-config.sh" ]; then
log_message "Connecting to Meshtastic radio and submitting $meshtastic_security_command"
eval "$meshtastic_security_command" 2>&1 | tee -a /tmp/femtofox-config.log
if [ $? -eq 1 ]; then
partial_failure=true
log_message "\033[0;31mSetting Meshtastic security settings FAILED.\033[0m" | tee -a /tmp/femtofox-config.log
fi
fi
for _ in {1..10}; do #do our successful config boot code

View file

@ -19,9 +19,11 @@ Options are:
-o OS info
-S Storage & RAM info
-t "enable" Enable/disable/start/stop/check ttyd (web terminal). Options: "enable" "disable" "start" "stop" "check"
-T Generate/overwrite ttyd encryption keys
-E Generate/overwrite SSH encryption keys
-C "service" Check if service is enabled, disabled, running
-R "command" Replace colors for dialog menus
-A "stop" Stop/start services that are using the meshtastic API so the Control for Meshtastic settings UI can run without interference. Options: "stop" "start"
-v Get Foxbuntu version
EOF
)
@ -61,8 +63,8 @@ act_led() {
}
cpu_info() {
local core="$(cat /sys/firmware/devicetree/base/model | tr -d '\0')"
local cpu_model="$(dmesg | grep "soc_id" | sed -n 's/.*soc_id: //p' | tr -d '\0')"; cpu_model="${cpu_model:-$(cat /proc/device-tree/compatible | sed 's/.*,\([^,]*\)$/\1/' | tr -d '\0')}"
local core="Luckfox Pico"
local cpu_model="$(tr -d '\0' </proc/device-tree/compatible | awk -F, '{print $1, $NF}')"
local cpu_architecture="$(uname -m) ($(dpkg --print-architecture) $(python3 -c "import platform; print(platform.architecture()[0])"))"
local cpu_temp="$(echo "scale=1; $(cat /sys/class/thermal/thermal_zone0/temp) / 1000" | bc)°C"
local cpu_speed="$(lscpu | grep "CPU min MHz" | awk '{print int($4)}')-$(lscpu | grep "CPU max MHz" | awk '{print int($4)}')mhz"
@ -91,11 +93,12 @@ Mnted drives:$mounted_drives"
}
os_info() {
local os_version="Foxbuntu v$(grep -oP 'major=\K[0-9]+' /etc/foxbuntu-release).$(grep -oP 'minor=\K[0-9]+' /etc/foxbuntu-release)$(output=$(grep -o 'patch=[1-9][0-9]*' /etc/foxbuntu-release | cut -d= -f2) && [ -n "$output" ] && echo ".$output")$(grep -oP 'hotfix=\K[a-z]+' /etc/foxbuntu-release) ($(lsb_release -d | awk -F'\t' '{print $2}') $(lsb_release -c | awk -F'\t' '{print $2}'))"
local os_version="$(femto-utils.sh -v) ($(lsb_release -d | awk -F'\t' '{print $2}') $(lsb_release -c | awk -F'\t' '{print $2}'))"
local system_uptime="$(uptime -p | awk '{$1=""; print $0}' | sed -e 's/ day\b/d/g' -e 's/ hour\b/h/g' -e 's/ hours\b/h/g' -e 's/ minute\b/m/g' -e 's/ minutes\b/m/g' | sed 's/,//g')"
local kernel_active_modules="$(lsmod | awk 'NR>1 {print $1}' | tr '\n' ' ' && echo)"
local kernel_boot_modules="$(modules=$(sed -n '6,$p' /etc/modules | sed ':a;N;$!ba;s/\n/, /g;s/, $//'); [ -z "$modules" ] && echo "none" || echo "$modules")"
local ttyd_enabled="$(ttyd "check" | sed 's/\x1b\[[0-9;]*m//g')"
local kernel_modules_blacklist="$(femto-kernel-modules.sh -y | sed 's/\x1B\[[0-9;]*m//g')" #remove underline
local ttyd_enabled="$(femto-utils.sh -C "ttyd")"
local logging_enabled="$(logging "check" | sed 's/\x1b\[[0-9;]*m//g')"
local act_led="$(femto-utils.sh -a "check" | sed -r 's/\x1B\[[0-9;]*[mK]//g')" #remove color from output
@ -106,6 +109,7 @@ Uptime:$system_uptime\n\
System time:$(date)\n\
K mods active:$kernel_active_modules\n\
K boot mods:$kernel_boot_modules\n\
K mod blcklst: $kernel_modules_blacklist
Web terminal:$ttyd_enabled\n\
Logging:$logging_enabled\n\
Activity LED:$act_led"
@ -142,7 +146,7 @@ peripherals_info() {
fi
done
fi
done <<< "$(echo "$(sudo i2cdetect -y 3)")"
done <<< "$(echo "$(timeout 3 i2cdetect -y 3)")" # when no i2c devices are connected, i2cdetect tries to connect for a solid 25 seconds. The timeout prevents this
[[ -z "$i2c_addresses" ]] && i2c_addresses="none detected" # if no addresses found, "none detected"
echo -e "LoRa radio:$lora_radio\n\
@ -201,44 +205,28 @@ logging() {
fi
}
ttyd() {
if [ "$1" = "disable" ]; then
systemctl disable ttyd
systemctl stop ttyd
echo "Disabled ttyd service."
exit 0
elif [ "$1" = "enable" ]; then
systemctl enable ttyd
echo "Enabled ttyd service."
systemctl start ttyd
exit 0
elif [ "$1" = "check" ]; then
if systemctl is-enabled ttyd &>/dev/null; then
if echo "$(systemctl status ttyd)" | grep -q "active (running)"; then
echo -e "\033[4m\033[0;34menabled and running\033[0m"
elif echo "$(systemctl status ttyd)" | grep -q "inactive (dead)"; then
echo -e "\033[4m\033[0;31menabled but not running\033[0m"
exit 1
else
echo "unknown"
fi
else
echo -e "\033[4m\033[0;31mdisabled\033[0m"
exit 1
fi
elif [ "$1" = "start" ]; then
echo "Starting/restarting ttyd service..."
systemctl restart ttyd
elif [ "$1" = "stop" ]; then
echo "Stopping ttyd service..."
systemctl stop ttyd
fi
# Dialog uses a different method to display colors, and is limited to only these 8.
replace_colors() {
input="$1"
input="${input//$(echo -e '\033[0;30m')/\\Z0}" # black
input="${input//$(echo -e '\033[0;31m')/\\Z1}" # red
input="${input//$(echo -e '\033[0;32m')/\\Z2}" # green
input="${input//$(echo -e '\033[0;33m')/\\Z3}" # yellow
input="${input//$(echo -e '\033[0;34m')/\\Z4}" # blue
input="${input//$(echo -e '\033[0;35m')/\\Z5}" # magenta
input="${input//$(echo -e '\033[0;36m')/\\Z6}" # cyan
input="${input//$(echo -e '\033[0;37m')/\\Z7}" # white
input="${input//$(echo -e '\033[7m')/\\Zr}" # invert
input="${input//$(echo -e '\033[4m')/\\Zu}" # underline
input="${input//$(echo -e '\e[39m')/\\Z0}" # reset colors not underline
input="${input//$(echo -e '\033[0m')/\\Zn}" # reset all
echo "$input"
}
while getopts ":harsl:ipcnoSt:TE" opt; do
while getopts ":harsl:ipcnoSEC:R:A:v" opt; do
case ${opt} in
h) # Option -h (help)
echo -e $help
echo -e "$help"
;;
a) # Option -a (ACT LED enable/disable/check)
act_led $2
@ -260,13 +248,6 @@ while getopts ":harsl:ipcnoSt:TE" opt; do
n) networking_info ;; # Option -n (Networing info)
o) os_info ;; # Option -o (OS info)
S) storage_info ;; # Option -S (Storage & RAM info)
t) ttyd $OPTARG ;; # Option -t (ttyd service manager)
T) # Option -T (new ttyd SSL keys)
openssl req -new -newkey rsa:4096 -days 3650 -nodes -x509 -keyout /etc/ssl/private/ttyd.key -out /etc/ssl/certs/ttyd.crt -subj "/CN=$(hostname)" -addext "subjectAltName=DNS:$(hostname)"
chmod 600 /etc/ssl/private/ttyd.key
chmod 644 /etc/ssl/certs/ttyd.crt
systemctl restart ttyd
;;
E) # Option -E (new SSH encryption keys)
rm /etc/ssh/ssh_host_*
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
@ -276,7 +257,69 @@ while getopts ":harsl:ipcnoSt:TE" opt; do
chown root:root /etc/ssh/ssh_host_*
systemctl restart ssh
;;
\?) # Unknown option)
C) # Option -C (Check service status)
if systemctl is-enabled $OPTARG &>/dev/null; then
state_message="\033[0;34m\033[4menabled\033[0m, "
else
state_message="\033[0;31m\033[4mdisabled\033[0m, "
fi
full_status=$(systemctl status $OPTARG)
if echo $full_status | grep -q "active (running)"; then
state_message+="\033[4m\033[0;34mrunning\033[0m"
exit_state=0
elif echo $full_status | grep -q "inactive (dead)"; then
state_message+="\033[4m\033[0;31mnot running\033[0m"
exit_state=1
elif echo $full_status | grep -q "failed"; then
state_message+="\033[4m\033[0;31mfailed\033[0m"
exit_state=1
elif echo $full_status | grep -q "activating"; then
state_message+="\033[4mactivating\033[0m"
exit_state=2
else
state_message+="\033[4munknown\033[0m"
exit_state=2
fi
echo -e "$state_message"
exit $exit_state
;;
R) # replace colors)
replace_colors "$OPTARG"
;;
A) # Stop/start services that are using the meshtastic API)
# this code cycles through all the software packages and looks for ones that are installed, conflict with Control and have a service that is enabled. If it finds such a software package, it either stops or starts it, according to $OPTARG
if [[ $OPTARG == "stop" ]]; then
action_text="Stopping"
action="s"
elif [[ $OPTARG == "start" ]]; then
action_text="Starting"
action="r"
else
echo "\`$OPTARG\` is not a valid argument for -A. Options are \"stop\" and \"start\"."
echo -e "$help"
exit 1
fi
for file in /usr/local/bin/packages/*.sh; do
filename=$(basename "$file")
[[ "$filename" == femto_* ]] && continue # Skip files starting with "femto_"
if sudo "$file" -I; then
if echo "$(sudo "$file" -C)" | grep -q "\"full control\" Meshtastic software"; then
service_state=$(sudo femto-utils.sh -C "$(sudo $file -E)")
if [[ $service_state =~ "enabled" ]] ; then
echo "$action_text $(sudo $file -N) service..."
eval "sudo $file -$action"
fi
fi
fi
done
;;
v) # get foxbuntu version)
echo "Foxbuntu v$(grep -oP 'major=\K[0-9]+' /etc/foxbuntu-release).$(grep -oP 'minor=\K[0-9]+' /etc/foxbuntu-release).$(grep -oP 'patch=\K[0-9]+' /etc/foxbuntu-release)$(grep -oP 'hotfix=\K\S+' /etc/foxbuntu-release)"
;;
\?) # Unknown argument)
echo -e "Unknown argument $1.\n$help"
;;
esac

View file

@ -0,0 +1,58 @@
#!/usr/bin/env bash
THRESHOLD=$((7 * 24 * 60 * 60)) # 1 week in seconds
LOGFILE="/var/log/time_change.log"
LAST_TIME_FILE="/tmp/last_time"
# Ensure the log file exists and is writable
if [ ! -f "$LOGFILE" ]; then
touch "$LOGFILE" || { echo "ERROR: Cannot create log file $LOGFILE"; exit 1; }
fi
if [ ! -w "$LOGFILE" ]; then
echo "ERROR: Log file $LOGFILE is not writable"
exit 1
fi
# Ensure the last time file exists and is writable
if [ ! -f "$LAST_TIME_FILE" ]; then
date +%s > "$LAST_TIME_FILE" || { echo "ERROR: Cannot create last time file $LAST_TIME_FILE"; exit 1; }
fi
if [ ! -w "$LAST_TIME_FILE" ]; then
echo "ERROR: Last time file $LAST_TIME_FILE is not writable"
exit 1
fi
while true; do
# Check if meshtasticd service is running
if ! systemctl is-active --quiet meshtasticd; then
#echo "meshtasticd service is not running. Skipping..." | tee -a "$LOGFILE"
sleep 30
continue
fi
NEW_TIME=$(date +%s)
# Ensure last_time file is readable before using it
if [ ! -r "$LAST_TIME_FILE" ]; then
echo "ERROR: Last time file $LAST_TIME_FILE is not readable" | tee -a "$LOGFILE"
exit 1
fi
OLD_TIME=$(cat "$LAST_TIME_FILE")
TIME_DIFF=$((NEW_TIME - OLD_TIME))
if [ "${TIME_DIFF#-}" -ge "$THRESHOLD" ]; then
echo "$(date) - Large time change detected ($TIME_DIFF seconds), restarting meshtasticd" | tee -a "$LOGFILE"
systemctl restart meshtasticd
fi
# Ensure last_time file is writable before updating it
if [ -w "$LAST_TIME_FILE" ]; then
echo "$NEW_TIME" > "$LAST_TIME_FILE"
else
echo "ERROR: Failed to write to $LAST_TIME_FILE" | tee -a "$LOGFILE"
exit 1
fi
sleep 30
done

View file

@ -17,11 +17,13 @@ get_mobile_wifi_state() {
set_mobile_wifi_state() {
local state="$1"
local meshtastic_output
if [[ "$state" == "up" ]]; then
meshtastic_output=$(meshtastic --host 127.0.0.1 --set network.wifi_enabled true 2>&1)
meshtastic_output=$(meshtastic --host 127.0.0.1 --set network.wifi_enabled true 2>&1 || true)
else
meshtastic_output=$(meshtastic --host 127.0.0.1 --set network.wifi_enabled false 2>&1)
meshtastic_output=$(meshtastic --host 127.0.0.1 --set network.wifi_enabled false 2>&1 || true)
fi
log "Set Meshtastic Wi-Fi state to $state. Output: $meshtastic_output"
}
@ -67,8 +69,8 @@ monitor_changes() {
while true; do
PID=$(ps -C meshtasticd -o pid= | tr -d ' ')
#if [[ -n "$PID" ]] && sudo lsof /dev/spidev0.0 | grep -q "$PID"; then
if [[ -n "$PID" ]] && sudo lsof /dev/spidev0.0 | grep -q "$PID" && [[ -d /sys/class/net/wlan0 ]]; then
#if [[ -n "$PID" ]] && sudo lsof /dev/spidev0.0 | grep -q "$PID" && [[ -d /sys/class/net/wlan0 ]]; then
if [[ -n "$PID" ]] && sudo lsof /dev/spidev0.0 | grep -q "$PID" && [[ -d /sys/class/net/wlan0 ]] && systemctl is-active --quiet meshtasticd; then
local current_mobile_state current_wlan_state
current_mobile_state=$(get_mobile_wifi_state)
current_wlan_state=$(cat /sys/class/net/wlan0/operstate)

View file

@ -1,58 +1,25 @@
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Try \`sudo femto-meshtasticd-config\`."
exit 1
fi
args="$@" # arguments to this script
interactive="true"
help=$(cat <<EOF
Arguments:
-h This message
Environment - must be first argument:
-x User UI is not terminal (script interactive unavailable)
Actions:
-i Install
-u Uninstall
-g Upgrade
-e Enable service, if applicable
-d Disable service, if applicable
-s Stop service
-r Start/Restart
-l Command to run software
Information:
-N Get name
-A Get author
-D Get description
-U Get URL
-O Get options supported by this script
-S Get service status
-L Get Install location
-C Get Conflicts
-I Check if installed. Returns an error if not installed
EOF
)
### For package maintainer:
# Fill the following fields and choose the options that are in use by this package
# Populate the install, uninstall and upgrade functions
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't really possible
# Arguments to the script are stored in $args
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't always possible
# This system supports both interactive and non-interactive installs. For non-interactive installs, $interactive="false". In this cause special instructions to the user should be given as user_message, such as `After installation, edit /opt/software/config.ini`
# Successful operations should `exit 0`, fails should `exit 1`
# Messages to the user (such as configuration instructions, explanatory error messages, etc) should be given as: `echo "user_message: text"`
# Everything following `user_message: ` will be displayed prominently to the user, so it must the last thing echoed
name="Contact" # software name
author="pdxlocations" # software author - OPTIONAL
description="A Text-Based Console UI for Meshtastic Nodes. Formerly called Curse Client.\nAfter install, run \`contact\` to launch." # software description - OPTIONAL (but strongly recommended!)
description="A Text-Based Console UI for Meshtastic Nodes. Formerly called Curses Client.\nAfter install, run \`contact\` to launch." # software description - OPTIONAL (but strongly recommended!)
URL="https://github.com/pdxlocations/contact/" # software URL. Can contain multiple URLs - OPTIONAL
options="xiuglNADUOLCI" # script options in use by software package. For example, for a package with no service, exclude `edsrS`
launch="python /opt/contact/main.py --host" # command to launch software, if applicable
options="xiuglNADUOLGTCI" # script options in use by software package. For example, for a package with no service, exclude `edsrS`
launch="echo \"Stopping conflicting services (if any), will restart after exit...\" && sudo femto-utils.sh -A stop && sudo -u ${SUDO_USER:-$(whoami)} env LANG=$LANG TERM=$TERM NCURSES_NO_UTF8_ACS=$NCURSES_NO_UTF8_ACS python /opt/contact/main.py --host && echo \"Restarting conflicting services (if any)...\" && sudo femto-utils.sh -A start" # command to launch software, if applicable
service_name="" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="/opt/contact" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
conflicts="" # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
license="$location/LICENSE" # file to cat to display license
license_name="GPL3" # license name, such as MIT, GPL3, custom, whatever. short text string.
conflicts="\"Full control\" Meshtastic software, such as TC²-BBS and Meshing Around - but only while running." # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
if [ $# -eq 0 ]; then
@ -68,6 +35,7 @@ install() {
echo "user_message: Git clone failed. Is internet connected?"
exit 1
fi
pip install -r $location/requirements.txt
chown -R femto $location #give ownership of installation directory to $user
git config --global --add safe.directory $location # prevents git error when updating
echo "Creating \`contact\` shortcut."
@ -115,53 +83,12 @@ check() {
fi
}
while getopts ":h$options" opt; do
case ${opt} in
h) # Option -h (help)
echo -e "$help"
;;
x) # Option -x (no user interaction available)
interactive="false"
;;
i) # Option -i (install)
install
;;
u) # Option -u (uninstall)
uninstall
;;
g) # Option -g (upgrade)
upgrade
;;
e) # Option -e (Enable service, if applicable)
systemctl enable $service_name
;;
d) # Option -d (Disable service, if applicable)
systemctl disable $service_name
;;
s) # Option -s (Stop service)
systemctl stop $service_name
;;
r) # Option -r (Start/Restart)
systemctl restart $service_name
;;
l) # Option -l (Run software)
echo "Launching $name..."
sudo -u ${SUDO_USER:-$(whoami)} $launch
;;
N) echo -e $name ;;
A) echo -e $author ;;
D) echo $description ;;
U) echo -e $URL ;;
O) echo -e $options ;;
S) # Option -S (Get service status)
systemctl status $service_name
;;
L) echo -e $location ;;
C) echo -e $conflicts ;;
I) # Option -I (Check if already installed)
check
;;
esac
done
# display license
license() {
echo -e "Contents of $license:\n\n $([[ -f "$license" ]] && awk -v max=2000 -v file="$license" '{ len += length($0) + 1; if (len <= max) print; else if (!cut) { cut=1; printf "%s...\n\nFile truncated, see %s for complete license.", substr($0, 1, max - len + length($0)), file; exit } }' "$license")"
}
# parse arguments
source /usr/local/bin/packages/femto_argument_parse.sh "$@"
exit 0

View file

@ -0,0 +1,74 @@
#!/bin/bash
### For package maintainer:
# Fill the following fields and choose the options that are in use by this package
# Populate the install, uninstall and upgrade functions
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't always possible
# This system supports both interactive and non-interactive installs. For non-interactive installs, $interaction="false". In this cause special instructions to the user should be given as user_message, such as `After installation, edit /opt/software/config.ini`
# Successful operations should `exit 0`, fails should `exit 1`
# Messages to the user (such as configuration instructions, explanatory error messages, etc) should be given as: `echo "user_message: text"`
# Everything following `user_message: ` will be displayed prominently to the user, so it must the last thing echoed
name="Control for Meshtastic" # software name
author="pdxlocations" # software author - OPTIONAL
description="Control for Meshtastic is a fully-featured Meshtastic configuration tool made for running in console, utilizing Curses.\n\nControl is installed by default on Femtofox and is used for Meshtastic configuration in femto-config. Uninstallation is not recommended." # software description - OPTIONAL (but strongly recommended!)
URL="https://github.com/pdxlocations/control" # software URL. Can contain multiple URLs - OPTIONAL
options="hxiuglNADUOLGTIC" # script options in use by software package. For example, for a package with no service, exclude `edsrS`
launch="echo \"Stopping conflicting services (if any), will restart after exit...\" && sudo femto-utils.sh -A stop && sudo -u ${SUDO_USER:-$(whoami)} env LANG=$LANG TERM=$TERM NCURSES_NO_UTF8_ACS=$NCURSES_NO_UTF8_ACS python /opt/control/main.py --host && echo \"Restarting conflicting services (if any)...\" && sudo femto-utils.sh -A start" # command to launch software, if applicable
license="/opt/control/LICENSE" # file to cat to display license
location="/opt/control" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
license="$location/LICENSE" # file to cat to display license
license_name="GPL3" # license name, such as MIT, GPL3, custom, whatever. short text string
conflicts="\"Full control\" Meshtastic software, such as TC²-BBS and Meshing Around - but only while running." # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
# install script
install() {
if ! git clone https://github.com/pdxlocations/control.git /opt/control; then
echo "user_message: Git clone failed. Is internet connected?"
exit 1
fi
pip install -r $location/requirements.txt
chown -R femto $location #give ownership of installation directory to $user
git config --global --add safe.directory $location # prevents git error when updating
echo "user_message: To launch, go to Meshtastic settings. Launching manually may conflict with \`full control\` Meshtastic software such as BBS."
exit 0 # should be `exit 1` if operation failed
}
# uninstall script
uninstall() {
rm -rf $location
echo "Removed \`$location\`."
echo "user_message: All files removed."
exit 0 # should be `exit 1` if operation failed
}
#upgrade script
upgrade() {
cd $location
if ! git pull; then
echo "user_message: Git pull failed. Is internet connected?"
exit 1
fi
exit 0
}
# Check if already installed. `exit 0` if yes, `exit 1` if no
check() {
#the following works for cloned repos, but not for apt installs
if [ -d "$location" ]; then
#echo "Already installed"
exit 0
else
#echo "Not installed"
exit 1
fi
}
# display license
license() {
echo -e "Contents of $license:\n\n $([[ -f "$license" ]] && awk -v max=2000 -v file="$license" '{ len += length($0) + 1; if (len <= max) print; else if (!cut) { cut=1; printf "%s...\n\nFile truncated, see %s for complete license.", substr($0, 1, max - len + length($0)), file; exit } }' "$license")"
}
# parse arguments
source /usr/local/bin/packages/femto_argument_parse.sh "$@"
exit 0

View file

@ -0,0 +1,106 @@
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Try \`sudo\`."
exit 1
fi
if [ $# -eq 0 ]; then
echo "No arguments provided."
echo -e "$help"
exit 1
fi
interactive="true" # by default, we're in interactive mode
help=$(cat <<EOF
Arguments:
-h This message
Environment - must be first argument:
-x User UI is not terminal (script interaction unavailable)
Actions:
-i Install
-u Uninstall
-a Interactive initialization script: code that must be run to initialize the installation prior to use, but can only be run from terminal
-g Upgrade
-e Enable service, if applicable
-d Disable service, if applicable
-s Stop service
-r Start/Restart
-l Command to run software
Information:
-N Get name
-A Get author
-D Get description
-U Get URL
-O Get options supported by this script
-S Get service status
-E Get service name
-L Get install location
-G Get license
-T Get license name
-P Get package name
-C Get Conflicts
-I Check if installed. Returns an error if not installed
EOF
)
while getopts ":$options" opt; do
case ${opt} in
h) # Option -h (help)
echo -e "$help"
;;
x) # Option -x (no user interaction available)
interactive="false"
;;
i) # Option -i (install)
install
;;
u) # Option -u (uninstall)
uninstall
;;
a) # Option -a (interactive initialization)
interactive_init
;;
g) # Option -g (upgrade)
upgrade
;;
e) # Option -e (Enable service, if applicable)
systemctl enable $service_name
;;
d) # Option -d (Disable service, if applicable)
systemctl disable $service_name
;;
s) # Option -s (Stop service)
systemctl stop $service_name
;;
r) # Option -r (Start/Restart)
systemctl restart $service_name
;;
l) # Option -l (Run software)
echo "Launching $name..."
eval "$launch"
;;
N) echo -e $name ;;
A) echo -e $author ;;
D) echo $description ;;
U) echo -e $URL ;;
O) echo -e $options ;;
S) # Option -S (Get service status)
systemctl status $service_name
;;
E) # Option -E (Get service name)
echo $service_name
;;
L) echo -e $location ;;
G) # Option -G (Get license)
license
;;
T) # Option -T (Get license name)
echo $license_name
;;
P) echo -e $package_name ;;
C) echo -e $conflicts ;;
I) # Option -I (Check if already installed)
check
;;
\?) exit 1 ;; # Unknown option)
esac
done

View file

@ -1,50 +1,8 @@
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Try \`sudo\`."
exit 1
fi
if [ $# -eq 0 ]; then
echo "No arguments provided."
echo -e "$help"
exit 1
fi
args="$@" # arguments to this script
interactive="true"
help=$(cat <<EOF
Arguments:
-h This message
Environment - must be first argument:
-x User UI is not terminal (script interaction unavailable)
Actions:
-i Install
-u Uninstall
-a Interactive initialization script: code that must be run to initialize the installation prior to use, but can only be run from terminal
-g Upgrade
-e Enable service, if applicable
-d Disable service, if applicable
-s Stop service
-r Start/Restart
-l Command to run software
Information:
-N Get name
-A Get author
-D Get description
-U Get URL
-O Get options supported by this script
-S Get service status
-L Get install location
-P Get package name
-C Get Conflicts
-I Check if installed. Returns an error if not installed
EOF
)
### For package maintainer:
# Fill the following fields and choose the options that are in use by this package
# Populate the install, uninstall and upgrade functions
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't really possible
# Arguments to the script are stored in $args
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't always possible
# This system supports both interactive and non-interactive installs. For non-interactive installs, $interaction="false". In this cause special instructions to the user should be given as user_message, such as `After installation, edit /opt/software/config.ini`
# Successful operations should `exit 0`, fails should `exit 1`
# Messages to the user (such as configuration instructions, explanatory error messages, etc) should be given as: `echo "user_message: text"`
@ -54,11 +12,14 @@ name="name" # software name
author="author" # software author - OPTIONAL
description="description" # software description - OPTIONAL (but strongly recommended!)
URL="URL" # software URL. Can contain multiple URLs - OPTIONAL
options="hxiuagedsrlNADUOSLPCI" # script options in use by software package. For example, for a package with no service, exclude `edsrS`
options="hxiuagedsrlNADUOSELGTPCI" # script options in use by software package. For example, for a package with no service, exclude `edsrS`
launch="/opt/package/run.sh" # command to launch software, if applicable
license="/opt/package/license" # file to cat to display license
service_name="service_name" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
package_name="apt_package" # apt package name, if applicable. Can be multiple packages separated by spaces, but if at least one is installed the package will show as "installed" even if the others aren't
location="/opt/location" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
license="$location/LICENSE" # file to cat to display license
license_name="GPL3" # license name, such as MIT, GPL3, custom, whatever. short text string
conflicts="package1, package2" # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
# install script
@ -89,72 +50,38 @@ upgrade() {
# Check if already installed. `exit 0` if yes, `exit 1` if no
check() {
# the following works for cloned repos, but not for apt installs
if [ -d "$location" ]; then
exit 0
else
exit 1
fi
## the following works for cloned repos, but not for apt installs
# if [ -d "$location" ]; then
# exit 0
# else
# exit 1
# fi
# this works for apt packages
if dpkg-query -W -f='${Status}' $package_name 2>/dev/null | grep -q "install ok installed"; then
exit 0
else
exit 1
fi
## this works for apt packages
# if dpkg-query -W -f='${Status}' $package_name 2>/dev/null | grep -q "install ok installed"; then
# exit 0
# else
# exit 1
# fi
}
while getopts ":$options" opt; do
case ${opt} in
h) # Option -h (help)
echo -e "$help"
;;
x) # Option -x (no user interaction available)
interaction="false"
;;
i) # Option -i (install)
install
;;
u) # Option -u (uninstall)
uninstall
;;
a) # Option -a (interactive initialization)
interactive_init
;;
g) # Option -g (upgrade)
upgrade
;;
e) # Option -e (Enable service, if applicable)
systemctl enable $service_name
;;
d) # Option -d (Disable service, if applicable)
systemctl disable $service_name
;;
s) # Option -s (Stop service)
systemctl stop $service_name
;;
r) # Option -r (Start/Restart)
systemctl restart $service_name
;;
l) # Option -l (Run software)
echo "Launching $name..."
sudo -u ${SUDO_USER:-$(whoami)} $launch
;;
N) echo -e $name ;;
A) echo -e $author ;;
D) echo $description ;;
U) echo -e $URL ;;
O) echo -e $options ;;
S) # Option -S (Get service status)
systemctl status $service_name
;;
L) echo -e $location ;;
P) echo -e $package_name ;;
C) echo -e $conflicts ;;
I) # Option -I (Check if already installed)
check
;;
esac
done
# display license - limit to 2000 chars
license() {
echo -e "Contents of $license:\n\n $([[ -f "$license" ]] && awk -v max=2000 -v file="$license" '{ len += length($0) + 1; if (len <= max) print; else if (!cut) { cut=1; printf "%s...\n\nFile truncated, see %s for complete license.", substr($0, 1, max - len + length($0)), file; exit } }' "$license")"
}
## custom getopts example for this package
# if [[ "$1" == "-k" ]]; then
# generate_keys
# fi
# parse arguments
source /usr/local/bin/packages/femto_argument_parse.sh "$@"
# extra help example for this package
# if [[ "$1" == "-h" ]]; then
# echo -e "Additional argument for this package:\n\
# -k Generate SSL keys. Must be first argument."
# fi
exit 0

View file

@ -1,49 +1,9 @@
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Try \`sudo\`."
exit 1
fi
if [ $# -eq 0 ]; then
echo "No arguments provided."
echo -e "$help"
exit 1
fi
args="$@" # arguments to this script
interactive="true"
help=$(cat <<EOF
Arguments:
-h This message
Environment - must be first argument:
-x User UI is not terminal (script interactive unavailable)
Actions:
-i Install
-u Uninstall
-a Interactive initialization script: code that must be run to initialize the installation prior to use, but can only be run from terminal
-g Upgrade
-e Enable service, if applicable
-d Disable service, if applicable
-s Stop service
-r Start/Restart
-l Command to run software
Information:
-N Get name
-A Get author
-D Get description
-U Get URL
-O Get options supported by this script
-S Get service status
-L Get Install location
-C Get Conflicts
-I Check if installed. Returns an error if not installed
EOF
)
### For package maintainer:
# Fill the following fields and choose the options that are in use by this package
# Populate the install, uninstall and upgrade functions
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't really possible
# Arguments to the script are stored in $args
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't always possible
# This system supports both interactive and non-interactive installs. For non-interactive installs, $interactive="false". In this cause special instructions to the user should be given as user_message, such as `After installation, edit /opt/software/config.ini`
# Successful operations should `exit 0`, fails should `exit 1`
# Messages to the user (such as configuration instructions, explanatory error messages, etc) should be given as: `echo "user_message: text"`
@ -53,11 +13,13 @@ name="Meshing Around" # software name
author="Spud" # software author - OPTIONAL
description="Meshing Around is a feature-rich bot designed to enhance your Meshtastic network experience with a variety of powerful tools and fun features. Connectivity and utility through text-based message delivery. Whether you're looking to perform network tests, send messages, or even play games, mesh_bot.py has you covered." # software description - OPTIONAL (but strongly recommended!)
URL="https://github.com/SpudGunMan/meshing-around" # software URL. Can contain multiple URLs - OPTIONAL
options="xiuagedsrNADUOSLCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiugedsrNADUOSELGTCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="" # command to launch software, if applicable
service_name="mesh_bot pong_bot mesh_bot_reporting" # the name of the service, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
service_name="mesh_bot" # the name of the service, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="/opt/meshing-around" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
conflicts="TC²-BBS, any other \"full control\" style bots" # comma delineated plain-text list of packages with which this package conflicts. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
license="$location/LICENSE" # file to cat to display license
license_name="GPL3" # license name, such as MIT, GPL3, custom, whatever. short text string
conflicts="TC²-BBS, other \"full control\" Meshtastic software, Control (only when running)." # comma delineated plain-text list of packages with which this package conflicts. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
# install script
install() {
@ -65,8 +27,11 @@ install() {
echo "user_message: Git clone failed. Is internet connected?"
exit 1
fi
pip install -r $location/requirements.txt
if [ "$interactive" = "true" ]; then #interactive install
interactive_init
"$location/install.sh" | tee /dev/tty
echo "user_message: To change settings, run \`sudo nano $location/config.ini\`"
exit 0
else
echo "user_message: IMPORTANT: To complete installation, run \`sudo $location/install.sh\`\nTo change settings, run \`sudo nano $location/config.ini\`"
exit 0
@ -96,8 +61,6 @@ uninstall() {
# code that must be run to initialize the installation prior to use, but can only be run from terminal
interactive_init() {
"$location/install.sh" | tee /dev/tty
echo "user_message: To change settings, run \`sudo nano $location/config.ini\`"
exit 0
}
@ -121,57 +84,12 @@ check() {
fi
}
while getopts ":h$options" opt; do
case ${opt} in
h) # Option -h (help)
echo -e "$help"
;;
x) # Option -x (no user interaction available)
echo "Running in non-interactive mode"
interactive="false"
;;
i) # Option -i (install)
install
;;
a) # Option -a (interactive initialization)
interactive_init
;;
u) # Option -u (uninstall)
uninstall
;;
g) # Option -g (upgrade)
upgrade
;;
e) # Option -e (Enable service, if applicable)
systemctl enable $service_name
;;
d) # Option -d (Disable service, if applicable)
systemctl disable $service_name
;;
s) # Option -s (Stop service)
systemctl stop $service_name
;;
r) # Option -r (Start/Restart)
systemctl restart $service_name
;;
l) # Option -l (Run software)
echo "Launching $name..."
sudo -u ${SUDO_USER:-$(whoami)} $launch
;;
N) echo -e $name ;;
A) echo -e $author ;;
D) echo $description ;;
U) echo -e $URL ;;
O) echo -e $options ;;
S) # Option -S (Get service status)
systemctl status $service_name
;;
L) echo -e $location ;;
C) echo -e $conflicts ;;
I) # Option -I (Check if already installed)
check
;;
esac
done
# display license
license() {
echo -e "Contents of $license:\n\n $([[ -f "$license" ]] && awk -v max=2000 -v file="$license" '{ len += length($0) + 1; if (len <= max) print; else if (!cut) { cut=1; printf "%s...\n\nFile truncated, see %s for complete license.", substr($0, 1, max - len + length($0)), file; exit } }' "$license")"
}
# parse arguments
source /usr/local/bin/packages/femto_argument_parse.sh "$@"
exit 0

View file

@ -1,49 +1,9 @@
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Try \`sudo\`."
exit 1
fi
if [ $# -eq 0 ]; then
echo "No arguments provided."
echo -e "$help"
exit 1
fi
args="$@" # arguments to this script
interaction="true"
help=$(cat <<EOF
Arguments:
-h This message
Environment - must be first argument:
-x User UI is not terminal (script interaction unavailable)
Actions:
-i Install
-u Uninstall
-g Upgrade
-e Enable service, if applicable
-d Disable service, if applicable
-s Stop service
-r Start/Restart
-l Command to run software
Information:
-N Get name
-A Get author
-D Get description
-U Get URL
-O Get options supported by this script
-S Get service status
-L Get install location
-P Get package name
-C Get Conflicts
-I Check if installed. Returns an error if not installed
EOF
)
### For package maintainer:
# Fill the following fields and choose the options that are in use by this package
# Populate the install, uninstall and upgrade functions
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't really possible
# Arguments to the script are stored in $args
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't always possible
# This system supports both interactive and non-interactive installs. For non-interactive installs, $interaction="false". In this cause special instructions to the user should be given as user_message, such as `After installation, edit /opt/software/config.ini`
# Successful operations should `exit 0`, fails should `exit 1`
# Messages to the user (such as configuration instructions, explanatory error messages, etc) should be given as: `echo "user_message: text"`
@ -54,11 +14,13 @@ name="Mosquitto MQTT Broker" # software name
author="Eclipse Foundation" # software author - OPTIONAL
description="Eclipse Mosquitto is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers.\n\nThe MQTT protocol provides a lightweight method of carrying out messaging using a publish/subscribe model. This makes it suitable for Internet of Things messaging such as with low power sensors or mobile devices such as phones, embedded computers or microcontrollers.\n\nThe Mosquitto project also provides a C library for implementing MQTT clients, and the very popular mosquitto_pub and mosquitto_sub command line MQTT clients.\n\nMosquitto is part of the Eclipse Foundation, and is an iot.eclipse.org project. The development is driven by Cedalo." # software description - OPTIONAL (but strongly recommended!)
URL="https://mosquitto.org/" # software URL. Can contain multiple URLs - OPTIONAL
options="xiugedsrNADUOSPCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiugedsrNADUOSEGTPCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="" # command to launch software, if applicable
service_name="mosquitto" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
package_name="mosquitto" # apt package name, if applicable
location="" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
license="usr/share/doc/mosquitto/copyright" # file to cat to display license
license_name="EPL/EDL" # license name, such as MIT, GPL3, custom, whatever. short text string
conflicts="" # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
# install script
@ -98,54 +60,12 @@ else
fi
}
while getopts ":h$options" opt; do
case ${opt} in
h) # Option -h (help)
echo -e "$help"
;;
x) # Option -x (no user interaction available)
interaction="false"
;;
i) # Option -i (install)
install
;;
u) # Option -u (uninstall)
uninstall
;;
g) # Option -g (upgrade)
upgrade
;;
e) # Option -e (Enable service, if applicable)
systemctl enable $service_name
;;
d) # Option -d (Disable service, if applicable)
systemctl disable $service_name
;;
s) # Option -s (Stop service)
systemctl stop $service_name
;;
r) # Option -r (Start/Restart)
systemctl restart $service_name
;;
l) # Option -l (Run software)
echo "Launching $name..."
sudo -u ${SUDO_USER:-$(whoami)} $launch
;;
N) echo -e $name ;;
A) echo -e $author ;;
D) echo $description ;;
U) echo -e $URL ;;
O) echo -e $options ;;
S) # Option -S (Get service status)
systemctl status $service_name
;;
L) echo -e $location ;;
P) echo -e $package_name ;;
C) echo -e $conflicts ;;
I) # Option -I (Check if already installed)
check
;;
esac
done
# display license
license() {
echo -e "Contents of $license:\n\n $([[ -f "$license" ]] && awk -v max=2000 -v file="$license" '{ len += length($0) + 1; if (len <= max) print; else if (!cut) { cut=1; printf "%s...\n\nFile truncated, see %s for complete license.", substr($0, 1, max - len + length($0)), file; exit } }' "$license")"
}
# parse arguments
source /usr/local/bin/packages/femto_argument_parse.sh "$@"
exit 0

View file

@ -1,49 +1,9 @@
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Try \`sudo\`."
exit 1
fi
if [ $# -eq 0 ]; then
echo "No arguments provided."
echo -e "$help"
exit 1
fi
args="$@" # arguments to this script
interaction="true"
help=$(cat <<EOF
Arguments:
-h This message
Environment - must be first argument:
-x User UI is not terminal (script interaction unavailable)
Actions:
-i Install
-u Uninstall
-g Upgrade
-e Enable service, if applicable
-d Disable service, if applicable
-s Stop service
-r Start/Restart
-l Command to run software
Information:
-N Get name
-A Get author
-D Get description
-U Get URL
-O Get options supported by this script
-S Get service status
-L Get install location
-P Get package name
-C Get Conflicts
-I Check if installed. Returns an error if not installed
EOF
)
### For package maintainer:
# Fill the following fields and choose the options that are in use by this package
# Populate the install, uninstall and upgrade functions
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't really possible
# Arguments to the script are stored in $args
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't always possible
# This system supports both interactive and non-interactive installs. For non-interactive installs, $interaction="false". In this cause special instructions to the user should be given as user_message, such as `After installation, edit /opt/software/config.ini`
# Successful operations should `exit 0`, fails should `exit 1`
# Messages to the user (such as configuration instructions, explanatory error messages, etc) should be given as: `echo "user_message: text"`
@ -54,10 +14,12 @@ name="Mosquitto MQTT Client" # software name
author="Eclipse Foundation" # software author - OPTIONAL
description="Eclipse Mosquitto is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers.\n\nThe MQTT protocol provides a lightweight method of carrying out messaging using a publish/subscribe model. This makes it suitable for Internet of Things messaging such as with low power sensors or mobile devices such as phones, embedded computers or microcontrollers.\n\nThe Mosquitto project also provides a C library for implementing MQTT clients, and the very popular mosquitto_pub and mosquitto_sub command line MQTT clients.\n\nMosquitto is part of the Eclipse Foundation, and is an iot.eclipse.org project. The development is driven by Cedalo." # software description - OPTIONAL (but strongly recommended!)
URL="https://mosquitto.org/" # software URL. Can contain multiple URLs - OPTIONAL
options="xiugedsrNADUOSPCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiugedsrNADUOSEGTPCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="" # command to launch software, if applicable
service_name="" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
license="usr/share/doc/mosquitto-clients/copyright" # file to cat to display license
license_name="EPL/EDL" # license name, such as MIT, GPL3, custom, whatever. short text string
package_name="mosquitto-clients" # apt package name, if applicable
conflicts="" # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
@ -96,54 +58,12 @@ else
fi
}
while getopts ":h$options" opt; do
case ${opt} in
h) # Option -h (help)
echo -e "$help"
;;
x) # Option -x (no user interaction available)
interaction="false"
;;
i) # Option -i (install)
install
;;
u) # Option -u (uninstall)
uninstall
;;
g) # Option -g (upgrade)
upgrade
;;
e) # Option -e (Enable service, if applicable)
systemctl enable $service_name
;;
d) # Option -d (Disable service, if applicable)
systemctl disable $service_name
;;
s) # Option -s (Stop service)
systemctl stop $service_name
;;
r) # Option -r (Start/Restart)
systemctl restart $service_name
;;
l) # Option -l (Run software)
echo "Launching $name..."
sudo -u ${SUDO_USER:-$(whoami)} $launch
;;
N) echo -e $name ;;
A) echo -e $author ;;
D) echo $description ;;
U) echo -e $URL ;;
O) echo -e $options ;;
S) # Option -S (Get service status)
systemctl status $service_name
;;
L) echo -e $location ;;
P) echo -e $package_name ;;
C) echo -e $conflicts ;;
I) # Option -I (Check if already installed)
check
;;
esac
done
# display license
license() {
echo -e "Contents of $license:\n\n $([[ -f "$license" ]] && awk -v max=2000 -v file="$license" '{ len += length($0) + 1; if (len <= max) print; else if (!cut) { cut=1; printf "%s...\n\nFile truncated, see %s for complete license.", substr($0, 1, max - len + length($0)), file; exit } }' "$license")"
}
# parse arguments
source /usr/local/bin/packages/femto_argument_parse.sh "$@"
exit 0

View file

@ -1,66 +1,27 @@
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Try \`sudo\`."
exit 1
fi
if [ $# -eq 0 ]; then
echo "No arguments provided."
echo -e "$help"
exit 1
fi
args="$@" # arguments to this script
interactive="true"
help=$(cat <<EOF
Arguments:
-h This message
Environment - must be first argument:
-x User UI is not terminal (script interaction unavailable)
Actions:
-i Install
-u Uninstall
-a Interactive initialization script: code that must be run to initialize the installation prior to use, but can only be run from terminal
-g Upgrade
-e Enable service, if applicable
-d Disable service, if applicable
-s Stop service
-r Start/Restart
-l Command to run software
Information:
-N Get name
-A Get author
-D Get description
-U Get URL
-O Get options supported by this script
-S Get service status
-L Get install location
-P Get package name
-C Get Conflicts
-I Check if installed. Returns an error if not installed
EOF
)
### For package maintainer:
# Fill the following fields and choose the options that are in use by this package
# Populate the install, uninstall and upgrade functions
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't really possible
# Arguments to the script are stored in $args
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't always possible
# This system supports both interactive and non-interactive installs. For non-interactive installs, $interaction="false". In this cause special instructions to the user should be given as user_message, such as `After installation, edit /opt/software/config.ini`
# Successful operations should `exit 0`, fails should `exit 1`
# Messages to the user (such as configuration instructions, explanatory error messages, etc) should be given as: `echo "user_message: text"`
# Everything following `user_message: ` will be displayed prominently to the user, so it must the last thing echoed
user_message="To connect to network share, enter \`\\\\femtofox\\home\` in Windows, \`smb://$(hostname)/home\` in MacOS or \`smbclient //$(hostname)/femto -U femto\` in Linux.\nDefault configuration shares /home/femto. Edit \`/etc/samba/smb.conf\` to add other shares.\n\nTroubleshooting: if Windows refuses to connect, especially after succeeding previously, hit [win]+R and enter \`net use * /delete\`."
init_instructions="To enable file sharing, run \`Initialize\` in the femto-config Samba menu, or enable the Samba service, run \`sudo smbpasswd -a femto\` to set a Samba password, and then restart the Samba service."
user_message="To connect to network share, enter \`\\\\femtofox\\home\` in Windows, \`smb://$(hostname)/home\` in MacOS or \`smbclient //$(hostname)/femto -U femto\` in Linux. Default configuration shares /home/femto. Edit \`/etc/samba/smb.conf\` to add other shares.\n\nTroubleshooting: if Windows refuses to connect after succeeding previously, hit [win]+R and enter \`net use * /delete\`."
init_instructions="To enable file sharing, run \`Initialize\` in the femto-config Samba menu to set a Samba password."
name="Samba File Sharing" # software name
author="Software Freedom Conservancy" # software author - OPTIONAL
description="Femtofox comes with Samba preinstalled but disabled. $init_instructions\n\n$user_message" # software description - OPTIONAL (but strongly recommended!)
URL="https://www.samba.org/" # software URL. Can contain multiple URLs - OPTIONAL
options="xiuagedsrNADUOSPCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiuagedsrNADUOSEGTPCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="" # command to launch software, if applicable
service_name="smbd nmbd" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
license="/usr/share/doc/samba/copyright" # file to cat to display license
license_name="GPL3" # license name, such as MIT, GPL3, custom, whatever. short text string
package_name="samba" # apt package name, if applicable
conflicts="" # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
@ -80,8 +41,6 @@ install() {
# uninstall script
uninstall() {
DEBIAN_FRONTEND=noninteractive apt remove -y $package_name 2>&1 | tee /dev/tty
echo "Removing unused dependencies..."
DEBIAN_FRONTEND=noninteractive apt autoremove -y $package_name 2>&1 | tee /dev/tty
echo "user_message: Some files may remain on system. To remove, run \`sudo apt remove --purge $package_name -y\` and \`sudo apt autoremove -y\`."
exit 0 # should be `exit 1` if operation failed
}
@ -96,7 +55,7 @@ interactive_init() {
exit 0
}
#upgrade script
# upgrade script
upgrade() {
echo "apt update can take a long while..."
DEBIAN_FRONTEND=noninteractive apt-get update -y 2>&1 | tee /dev/tty | grep -q "Err" && { echo "user_message: apt update failed. Is internet connected?"; exit 1; }
@ -113,57 +72,12 @@ else
fi
}
while getopts ":h$options" opt; do
case ${opt} in
h) # Option -h (help)
echo -e "$help"
;;
x) # Option -x (no user interaction available)
interaction="false"
;;
i) # Option -i (install)
install
;;
a) # Option -a (interactive initialization)
interactive_init
;;
u) # Option -u (uninstall)
uninstall
;;
g) # Option -g (upgrade)
upgrade
;;
e) # Option -e (Enable service, if applicable)
systemctl enable $service_name
;;
d) # Option -d (Disable service, if applicable)
systemctl disable $service_name
;;
s) # Option -s (Stop service)
systemctl stop $service_name
;;
r) # Option -r (Start/Restart)
systemctl restart $service_name
;;
l) # Option -l (Run software)
echo "Launching $name..."
sudo -u ${SUDO_USER:-$(whoami)} $launch
;;
N) echo -e $name ;;
A) echo -e $author ;;
D) echo $description ;;
U) echo -e $URL ;;
O) echo -e $options ;;
S) # Option -S (Get service status)
systemctl status $service_name
;;
L) echo -e $location ;;
P) echo -e $package_name ;;
C) echo -e $conflicts ;;
I) # Option -I (Check if already installed)
check
;;
esac
done
# display license
license() {
echo -e "Contents of $license:\n\n $([[ -f "$license" ]] && awk -v max=2000 -v file="$license" '{ len += length($0) + 1; if (len <= max) print; else if (!cut) { cut=1; printf "%s...\n\nFile truncated, see %s for complete license.", substr($0, 1, max - len + length($0)), file; exit } }' "$license")"
}
# parse arguments
source /usr/local/bin/packages/femto_argument_parse.sh "$@"
exit 0

View file

@ -1,48 +1,9 @@
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Try \`sudo\`."
exit 1
fi
if [ $# -eq 0 ]; then
echo "No arguments provided."
echo -e "$help"
exit 1
fi
args="$@" # arguments to this script
interactive="true"
help=$(cat <<EOF
Arguments:
-h This message
Environment - must be first argument:
-x User UI is not terminal (script interactive unavailable)
Actions:
-i Install
-u Uninstall
-g Upgrade
-e Enable service, if applicable
-d Disable service, if applicable
-s Stop service
-r Start/Restart
-l Command to run software
Information:
-N Get name
-A Get author
-D Get description
-U Get URL
-O Get options supported by this script
-S Get service status
-L Get Install location
-C Get Conflicts
-I Check if installed. Returns an error if not installed
EOF
)
### For package maintainer:
# Fill the following fields and choose the options that are in use by this package
# Populate the install, uninstall and upgrade functions
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't really possible
# Arguments to the script are stored in $args
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't always possible
# This system supports both interactive and non-interactive installs. For non-interactive installs, $interactive="false". In this cause special instructions to the user should be given as user_message, such as `After installation, edit /opt/software/config.ini`
# Successful operations should `exit 0`, fails should `exit 1`
# Messages to the user (such as configuration instructions, explanatory error messages, etc) should be given as: `echo "user_message: text"`
@ -53,11 +14,13 @@ name="TC²-BBS" # software name
author="The Comms Channel" # software author - OPTIONAL
description="The TC²-BBS system integrates with Meshtastic devices. The system allows for message handling, bulletin boards, mail systems, and a channel directory." # software description - OPTIONAL (but strongly recommended!)
URL="https://github.com/TheCommsChannel/TC2-BBS-mesh" # software URL. Can contain multiple URLs - OPTIONAL
options="xiugedsrNADUOSLCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiugedsrNADUOSELGTCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="python /opt/TC2-BBS-mesh/server.py" # command to launch software, if applicable
service_name="mesh-bbs" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="/opt/TC2-BBS-mesh" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
conflicts="Meshing Around, other \"full control\" packages" # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
license="$location/LICENSE" # file to cat to display license
license_name="GPL3" # license name, such as MIT, GPL3, custom, whatever. short text string
conflicts="Meshing Around, other \"full control\" Meshtastic software, Control (only when running)." # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
# install script
install() {
@ -65,6 +28,7 @@ install() {
echo "user_message: Git clone failed. Is internet connected?"
exit 1
fi
pip install -r $location/requirements.txt
chown -R femto $location #give ownership of installation directory to $user
git config --global --add safe.directory $location # prevents git error when updating
@ -121,53 +85,12 @@ check() {
fi
}
while getopts ":h$options" opt; do
case ${opt} in
h) # Option -h (help)
echo -e "$help"
;;
x) # Option -x (no user interaction available)
interactive="false"
;;
i) # Option -i (install)
install
;;
u) # Option -u (uninstall)
uninstall
;;
g) # Option -g (upgrade)
upgrade
;;
e) # Option -e (Enable service, if applicable)
systemctl enable $service_name
;;
d) # Option -d (Disable service, if applicable)
systemctl disable $service_name
;;
s) # Option -s (Stop service)
systemctl stop $service_name
;;
r) # Option -r (Start/Restart)
systemctl restart $service_name
;;
l) # Option -l (Run software)
echo "Launching $name..."
sudo -u ${SUDO_USER:-$(whoami)} $launch
;;
N) echo -e $name ;;
A) echo -e $author ;;
D) echo $description ;;
U) echo -e $URL ;;
O) echo -e $options ;;
S) # Option -S (Get service status)
systemctl status $service_name
;;
L) echo -e $location ;;
C) echo -e $conflicts ;;
I) # Option -I (Check if already installed)
check
;;
esac
done
# display license
license() {
echo -e "Contents of $license:\n\n $([[ -f "$license" ]] && awk -v max=2000 -v file="$license" '{ len += length($0) + 1; if (len <= max) print; else if (!cut) { cut=1; printf "%s...\n\nFile truncated, see %s for complete license.", substr($0, 1, max - len + length($0)), file; exit } }' "$license")"
}
# parse arguments
source /usr/local/bin/packages/femto_argument_parse.sh "$@"
exit 0

View file

@ -0,0 +1,110 @@
#!/bin/bash
### For package maintainer:
# Fill the following fields and choose the options that are in use by this package
# Populate the install, uninstall and upgrade functions
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't always possible
# This system supports both interactive and non-interactive installs. For non-interactive installs, $interaction="false". In this cause special instructions to the user should be given as user_message, such as `After installation, edit /opt/software/config.ini`
# Successful operations should `exit 0`, fails should `exit 1`
# Messages to the user (such as configuration instructions, explanatory error messages, etc) should be given as: `echo "user_message: text"`
# Everything following `user_message: ` will be displayed prominently to the user, so it must the last thing echoed
name="ttyd Web Terminal" # software name
author="Shuanglei Tao" # software author - OPTIONAL
description="ttyd is a simple command-line tool for sharing terminal over the web.\n\nWhen running, ttyd is available at https://$(hostname).local:7681\nttyd is installed and enabled by default on Foxbuntu.\n\nSSL encryption is provided by keys generated during first-boot or during installation. Your browser may give a warning (net::ERR_CERT_AUTHORITY_INVALID) about the self-signed encryption certificate. This is normal. In Chromium (Chrome, Edge) click \"Advanced\" and \"Continue to femtofox.local (unsafe)\"" # software description - OPTIONAL (but strongly recommended!)
URL="https://github.com/tsl0922/ttyd" # software URL. Can contain multiple URLs - OPTIONAL
options="hxiugedsrNADUOSELGTCIk" # script options in use by software package. For example, for a package with no service, exclude `edsrS`
launch="" # command to launch software, if applicable
service_name="ttyd" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
package_name="" # apt package name, if applicable. Can be multiple packages separated by spaces, but if at least one is installed the package will show as "installed" even if the others aren't
location="/opt/ttyd" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
license="$location/LICENSE" # file to cat to display license
license_name="MIT" # license name, such as MIT, GPL3, custom, whatever. short text string
conflicts="" # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
# install script
install() {
mkdir $location
if ! wget -P "$location/" https://raw.githubusercontent.com/tsl0922/ttyd/refs/heads/main/LICENSE; then # we are required by ttyd to download and store the license
echo "user_message: Download failed. Is internet connected?"
exit 1
fi
if ! wget -qO- https://api.github.com/repos/tsl0922/ttyd/releases/latest | grep "browser_download_url" | grep "armhf" | cut -d '"' -f 4 | xargs wget -O $location/ttyd; then
echo "user_message: Download failed. Is internet connected?"
exit 1
fi
chmod +x /opt/ttyd/ttyd
echo "Generating SSL keys..."
generate_keys
systemctl enable ttyd
systemctl start ttyd
echo "user_message: ttyd service started and should be available at https://$(hostname).local:7681"
exit 0 # should be `exit 1` if operation failed
}
# uninstall script
uninstall() {
systemctl disable ttyd
systemctl stop ttyd
rm -rf $location
echo "user_message: Binary removed. Service has been disabled but service file retained. SSL encryption keys have been retained."
exit 0 # should be `exit 1` if operation failed
}
# code that must be run to initialize the installation prior to use, but can only be run from terminal
interactive_init() {
exit 0 # should be `exit 1` if operation failed
}
# upgrade script
upgrade() {
systemctl stop ttyd
if ! wget -qO- https://api.github.com/repos/tsl0922/ttyd/releases/latest | grep "browser_download_url" | grep "armhf" | cut -d '"' -f 4 | xargs wget -O $location/ttyd; then
echo "user_message: Download failed. Is internet connected?"
exit 1
fi
systemctl start ttyd
echo "user_message: New binary downloaded and service restarted."
exit 0 # should be `exit 1` if operation failed
}
# Check if already installed. `exit 0` if yes, `exit 1` if no
check() {
# the following works for cloned repos, but not for apt installs
if [ -d "$location" ]; then
exit 0
else
exit 1
fi
}
# display license
license() {
echo -e "Contents of $license:\n\n $([[ -f "$license" ]] && awk -v max=2000 -v file="$license" '{ len += length($0) + 1; if (len <= max) print; else if (!cut) { cut=1; printf "%s...\n\nFile truncated, see %s for complete license.", substr($0, 1, max - len + length($0)), file; exit } }' "$license")"
}
# custom for this package
generate_keys() {
openssl req -new -newkey rsa:4096 -days 3650 -nodes -x509 -keyout /etc/ssl/private/ttyd.key -out /etc/ssl/certs/ttyd.crt -subj "/CN=$(hostname)" -addext "subjectAltName=DNS:$(hostname)"
chmod 600 /etc/ssl/private/ttyd.key
chmod 644 /etc/ssl/certs/ttyd.crt
if systemctl is-enabled ttyd &>/dev/null; then # if service is enabled
systemctl restart ttyd
fi
}
# custom getopts for ttyd: generate key
if [[ "$1" == "-k" ]]; then
generate_keys
fi
# parse arguments
source /usr/local/bin/packages/femto_argument_parse.sh "$@"
# extra help for this package
if [[ "$1" == "-h" ]]; then
echo -e "Additional argument for this package:\n\
-k Generate SSL keys. Must be first argument."
fi
exit 0

View file

@ -1,3 +1,17 @@
Femtofox is comprised of two projects, with two different licenses:
1. Femtofox - the hardware, which is licensed "CC BY-NC-ND - noncommercial". Summary: you may copy and share and modify the hardware files, but cannot sell them without license from Femtofox, and must give attribution to Femtofox.
2. Foxbuntu - refers to the modifications to Ubuntu made as part of the Femtofox project, which is licensed GNU GPLv3. Summary: you may use, modify and distribute (including for commercial purposes) Foxbuntu, but must give attribution to Femtofox and distribute this license with your project. Any modified version must remain open source.
See below for the full license texts.
Hardware (Femtofox) license:
Summary:
Attribution — You must give appropriate credit , provide a link to the license, and indicate if changes were made . You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
NonCommercial — You may not use the material for commercial purposes .
NoDerivatives — If you remix, transform, or build upon the material, you may not distribute the modified material.
Contact us to license Femtofox.
The license:
Attribution-NonCommercial-NoDerivatives 4.0 International
@ -400,4 +414,682 @@ understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.
Creative Commons may be contacted at creativecommons.org.
Software (Foxbuntu) license:
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View file

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 100 55" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(0.802386,0,0,0.460028,-421.748,-122.127)">
<g transform="matrix(0.579082,0,0,1.01004,460.975,-39.6867)">
<path d="M250.908,330.267L193.126,415.005L180.938,406.694L244.802,313.037C246.174,311.024 248.453,309.819 250.889,309.816C253.326,309.814 255.606,311.015 256.982,313.026L320.994,406.536L308.821,414.869L250.908,330.267Z"/>
</g>
<g transform="matrix(0.582378,0,0,1.01579,485.019,-211.182)">
<path d="M87.642,581.398L154.757,482.977L142.638,474.713L75.523,573.134L87.642,581.398Z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1 KiB

View file

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 100 55" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(0.802386,0,0,0.460028,-421.748,-122.127)">
<g transform="matrix(0.579082,0,0,1.01004,460.975,-39.6867)">
<path d="M250.908,330.267L193.126,415.005L180.938,406.694L244.802,313.037C246.174,311.024 248.453,309.819 250.889,309.816C253.326,309.814 255.606,311.015 256.982,313.026L320.994,406.536L308.821,414.869L250.908,330.267Z" style="fill:white;"/>
</g>
<g transform="matrix(0.582378,0,0,1.01579,485.019,-211.182)">
<path d="M87.642,581.398L154.757,482.977L142.638,474.713L75.523,573.134L87.642,581.398Z" style="fill:white;"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View file

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="512" height="512" viewBox="0 0 512 512" xml:space="preserve">
<desc>Created with Fabric.js 4.6.0</desc>
<defs>
</defs>
<g transform="matrix(1 0 0 1 256 256)" id="xYQ9Gk9Jwpgj_HMOXB3F_" >
<path style="stroke: rgb(213,130,139); stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(103,234,148); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-256, -256)" d="M 0 0 L 512 0 L 512 512 L 0 512 z" stroke-linecap="round" />
</g>
<g transform="matrix(1.79 0 0 1.79 313.74 258.36)" id="1xBsk2n9FZp60Rz1O-ceJ" >
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: round; stroke-miterlimit: 2; fill: rgb(44,45,60); fill-rule: evenodd; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-250.97, -362.41)" d="M 250.908 330.267 L 193.126 415.005 L 180.938 406.694 L 244.802 313.037 C 246.174 311.024 248.453 309.819 250.889 309.816 C 253.326 309.814 255.606 311.015 256.982 313.026 L 320.994 406.536 L 308.821 414.869 L 250.908 330.267 Z" stroke-linecap="round" />
</g>
<g transform="matrix(1.81 0 0 1.81 145 256.15)" id="KxN7E9YpbyPgz0S4z4Cl6" >
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: round; stroke-miterlimit: 2; fill: rgb(44,45,60); fill-rule: evenodd; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-115.14, -528.06)" d="M 87.642 581.398 L 154.757 482.977 L 142.638 474.713 L 75.523 573.134 L 87.642 581.398 Z" stroke-linecap="round" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

File diff suppressed because one or more lines are too long

View file

@ -1,30 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
<link rel="icon" href="/favicon.ico" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180" />
<link rel="manifest" href="site.webmanifest" />
<link rel="mask-icon" href="Logo_Black.svg" color="#67ea94" />
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@xz/fonts@1/serve/cascadia-code.min.css"
/>
<meta name="theme-color" content="#67ea94" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0"
/>
<meta name="description" content="Meshtastic Web App" />
<title>Meshtastic Web</title>
<script type="module" crossorigin src="/index-b9vwykds.js"></script>
<link rel="stylesheet" crossorigin href="/index-wV0rbIjU.css">
</head>
<body>
<div id="root"></div>
<noscript>You need to enable JavaScript to run this app.</noscript>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -1,16 +0,0 @@
{
"name": "Meshtastic",
"short_name": "Meshtastic",
"start_url": ".",
"description": "Meshtastic web app",
"icons": [
{
"src": "/icon.svg",
"sizes": "any",
"type": "image/svg+xml"
}
],
"theme_color": "#67ea94",
"background_color": "#67ea94",
"display": "standalone"
}

View file

@ -0,0 +1,538 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
*/
#include "rv1106-evb.dtsi"
#include <dt-bindings/input/input.h>
#include <dt-bindings/display/media-bus-format.h>
/ {
chosen {
bootargs = "earlycon=uart8250,mmio32,0xff4c0000 console=ttyFIQ0 root=/dev/mmcblk0p7 rootwait snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=0";
};
backlight: backlight {
status = "okay";
compatible = "pwm-backlight";
pwms = <&pwm1 0 100000 50000>;
brightness-levels = <
0 1 2 3 4 5 6 7
8 9 10 11 12 13 14 15
16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
64 65 66 67 68 69 70 71
72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87
88 89 90 91 92 93 94 95
96 97 98 99 100 101 102 103
104 105 106 107 108 109 110 111
112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127
128 129 130 131 132 133 134 135
136 137 138 139 140 141 142 143
144 145 146 147 148 149 150 151
152 153 154 155 156 157 158 159
160 161 162 163 164 165 166 167
168 169 170 171 172 173 174 175
176 177 178 179 180 181 182 183
184 185 186 187 188 189 190 191
192 193 194 195 196 197 198 199
200 201 202 203 204 205 206 207
208 209 210 211 212 213 214 215
216 217 218 219 220 221 222 223
224 225 226 227 228 229 230 231
232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255>;
default-brightness-level = <255>;
};
panel: panel {
compatible = "simple-panel";
backlight = <&backlight>;
reset-gpios = <&gpio0 RK_PA1 GPIO_ACTIVE_LOW>;
reset-delay-ms = <200>;
status = "okay";
bus-format = <MEDIA_BUS_FMT_RGB666_1X18>;
width-mm = <85>;
height-mm = <85>;
display-timings {
native-mode = <&timing0>;
timing0: timing0 {
clock-frequency = <30000000>;
hactive = <720>;
vactive = <720>;
hback-porch = <44>;
hfront-porch = <46>;
vback-porch = <18>;
vfront-porch = <16>;
hsync-len = <2>;
vsync-len = <2>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};
port {
panel_in_rgb: endpoint {
remote-endpoint = <&rgb_out_panel>;
};
};
};
reserved_memory: reserved-memory {
status = "okay";
#address-cells = <1>;
#size-cells = <1>;
ranges;
drm_logo: drm-logo@00000000 {
compatible = "rockchip,drm-logo";
reg = <0x0 0x0>;
};
linux,cma {
status = "okay";
compatible = "shared-dma-pool";
inactive;
reusable;
size = <0xA00000>; //10M
linux,cma-default;
};
mmc_ecsd: mmc@3f000 {
reg = <0x3f000 0x00001000>;
};
};
acodec_sound: acodec-sound {
compatible = "simple-audio-card";
simple-audio-card,name = "rv1106-acodec";
simple-audio-card,format = "i2s";
simple-audio-card,mclk-fs = <256>;
simple-audio-card,cpu {
sound-dai = <&i2s0_8ch>;
};
simple-audio-card,codec {
sound-dai = <&acodec>;
};
};
dsm_sound: dsm-sound {
status = "disabled";
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,mclk-fs = <256>;
simple-audio-card,name = "rockchip,dsm-sound";
simple-audio-card,bitclock-master = <&sndcodec>;
simple-audio-card,frame-master = <&sndcodec>;
sndcpu: simple-audio-card,cpu {
sound-dai = <&i2s0_8ch>;
};
sndcodec: simple-audio-card,codec {
sound-dai = <&dsm>;
};
};
vcc_1v8: vcc-1v8 {
compatible = "regulator-fixed";
regulator-name = "vcc_1v8";
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
vcc_3v3: vcc-3v3 {
compatible = "regulator-fixed";
regulator-name = "vcc_3v3";
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
vdd_arm: vdd-arm {
compatible = "regulator-fixed";
regulator-name = "vdd_arm";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1000000>;
regulator-init-microvolt = <900000>;
regulator-always-on;
regulator-boot-on;
};
leds: leds {
compatible = "gpio-leds";
work_led: work{
gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "activity";
default-state = "on";
};
};
};
/***************************** audio ********************************/
&i2s0_8ch {
#sound-dai-cells = <0>;
status = "okay";
};
&acodec {
#sound-dai-cells = <0>;
pa-ctl-gpios = <&gpio3 RK_PD3 GPIO_ACTIVE_HIGH>;
status = "okay";
};
/************************* FIQ_DUBUGGER ****************************/
&fiq_debugger {
rockchip,irq-mode-enable = <1>;
status = "okay";
};
/***************************** USB *********************************/
&u2phy {
status = "okay";
};
&u2phy_otg {
status = "okay";
};
&usbdrd {
status = "okay";
};
&usbdrd_dwc3 {
extcon = <&u2phy>;
status = "okay";
};
/***************************** DSM *********************************/
&dsm {
status = "disabled";
};
&cpu0 {
cpu-supply = <&vdd_arm>;
};
/*************************** CSI *********************************/
&csi2_dphy_hw {
status = "okay";
};
&csi2_dphy0 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
csi_dphy_input0: endpoint@0 {
reg = <0>;
remote-endpoint = <&sc3336_out>;
data-lanes = <1 2>;
};
};
port@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
csi_dphy_output: endpoint@0 {
reg = <0>;
remote-endpoint = <&mipi_csi2_input>;
};
};
};
};
&i2c4 {
status = "okay";
clock-frequency = <400000>;
pinctrl-names = "default";
// pinctrl-0 = <&i2c4m2_xfer>;
sc3336: sc3336@30 {
compatible = "smartsens,sc3336";
status = "okay";
reg = <0x30>;
clocks = <&cru MCLK_REF_MIPI0>;
clock-names = "xvclk";
reset-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&mipi_refclk_out0>;
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "CMK-OT2119-PC1";
rockchip,camera-module-lens-name = "30IRC-F16";
port {
sc3336_out: endpoint {
remote-endpoint = <&csi_dphy_input0>;
data-lanes = <1 2>;
};
};
};
};
&mipi0_csi2 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
mipi_csi2_input: endpoint@1 {
reg = <1>;
remote-endpoint = <&csi_dphy_output>;
};
};
port@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
mipi_csi2_output: endpoint@0 {
reg = <0>;
remote-endpoint = <&cif_mipi_in>;
};
};
};
};
&rkcif {
status = "okay";
};
&rkcif_mipi_lvds {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mipi_pins>;
port {
/* MIPI CSI-2 endpoint */
cif_mipi_in: endpoint {
remote-endpoint = <&mipi_csi2_output>;
};
};
};
&rkcif_mipi_lvds_sditf {
status = "okay";
port {
/* MIPI CSI-2 endpoint */
mipi_lvds_sditf: endpoint {
remote-endpoint = <&isp_in>;
};
};
};
&rkisp {
status = "okay";
};
&rkisp_vir0 {
status = "okay";
port@0 {
isp_in: endpoint {
remote-endpoint = <&mipi_lvds_sditf>;
};
};
};
/***************************** ADC ********************************/
&saradc {
status = "okay";
vref-supply = <&vcc_1v8>;
};
&tsadc {
status = "okay";
};
/**************************** LCD/TP ******************************/
&pwm1 {
status = "okay";
pinctrl-names = "active";
pinctrl-0 = <&pwm1m2_pins>;
};
&display_subsystem {
status = "okay";
logo-memory-region = <&drm_logo>;
};
&rgb {
status = "disabled";
pinctrl-names = "default";
pinctrl-0 = <&lcd_pins>;
ports {
rgb_out: port@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
rgb_out_panel: endpoint@0 {
reg = <0>;
remote-endpoint = <&panel_in_rgb>;
};
};
};
};
&rgb_in_vop {
status = "okay";
};
&route_rgb {
status = "disabled";
};
&vop {
status = "okay";
};
&i2c3 {
clock-frequency = <100000>;
GT911:touchscreen {
compatible = "goodix,gt911";
reg = <0x14>;
interrupt-parent = <&gpio0>;
interrupts = <RK_PA3 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
};
};
/**************************** PINCTRL ******************************/
// SPI
&spi0 {
pinctrl-0 = <&spi0m0_clk &spi0m0_miso &spi0m0_mosi &spi0m0_cs0>;
#address-cells = <1>;
#size-cells = <0>;
spidev@0 {
compatible = "rockchip,spidev";
spi-max-frequency = <50000000>;
reg = <0>;
};
};
// I2C
&i2c1 {
pinctrl-0 = <&i2c1m1_xfer>;
};
&i2c2 {
pinctrl-0 = <&i2c2m0_xfer>;
};
&i2c3 {
pinctrl-0 = <&i2c3m0_xfer &i2c3m1_xfer &i2c3m2_xfer &tp_rst &tp_irq>;
};
&i2c4 {
pinctrl-0 = <&i2c4m0_xfer &i2c4m1_xfer &i2c4m2_xfer>;
};
// UART
&uart0 {
pinctrl-0 = <&uart0m0_xfer &uart0m1_xfer>;
};
&uart1 {
pinctrl-0 = <&uart1m1_xfer>;
};
&uart3 {
pinctrl-0 = <&uart3m0_xfer &uart3m1_xfer>;
};
&uart4 {
pinctrl-0 = <&uart4m0_xfer>;
};
&uart5 {
pinctrl-0 = <&uart5m1_xfer>;
};
// PWM
&pwm0 {
pinctrl-0 = <&pwm0m1_pins>;
};
&pwm2 {
pinctrl-0 = <&pwm2m1_pins &pwm2m2_pins>;
};
&pwm3 {
pinctrl-0 = <&pwm3m2_pins>;
};
&pwm4 {
pinctrl-0 = <&pwm4m0_pins &pwm4m1_pins &pwm4m2_pins>;
};
&pwm5 {
pinctrl-0 = <&pwm5m1_pins &pwm5m2_pins>;
};
&pwm6 {
pinctrl-0 = <&pwm6m1_pins &pwm6m2_pins>;
};
&pwm7 {
pinctrl-0 = <&pwm7m0_pins &pwm7m1_pins>;
};
&pwm8 {
pinctrl-0 = <&pwm8m1_pins>;
};
&pwm9 {
pinctrl-0 = <&pwm9m1_pins>;
};
&pwm10 {
pinctrl-0 = <&pwm10m1_pins &pwm10m2_pins>;
};
&pwm11 {
pinctrl-0 = <&pwm11m1_pins &pwm11m2_pins>;
};
&pinctrl {
spi0 {
spi0m0_clk: spi0m0-clk {
rockchip,pins = <1 RK_PC1 4 &pcfg_pull_none>;
};
spi0m0_mosi: spi0m0-mosi {
rockchip,pins = <1 RK_PC2 6 &pcfg_pull_none>;
};
spi0m0_miso: spi0m0-miso {
rockchip,pins = <1 RK_PC3 6 &pcfg_pull_none>;
};
spi0m0_cs0: spi0m0-cs0 {
rockchip,pins = <1 RK_PC0 4 &pcfg_pull_none>;
};
};
touchscreen {
tp_rst:tp-rst {
rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
};
tp_irq:tp-irq {
rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
};

View file

@ -1368,7 +1368,25 @@ CONFIG_SCSI_UFSHCD=y
CONFIG_NETDEVICES=y
CONFIG_MII=y
# CONFIG_NET_CORE is not set
CONFIG_NET_CORE=y
# CONFIG_BONDING is not set
# CONFIG_DUMMY is not set
# CONFIG_WIREGUARD is not set
# CONFIG_EQUALIZER is not set
# CONFIG_NET_FC is not set
# CONFIG_NET_TEAM is not set
# CONFIG_MACVLAN is not set
# CONFIG_IPVLAN is not set
# CONFIG_VXLAN is not set
# CONFIG_GENEVE is not set
# CONFIG_BAREUDP is not set
# CONFIG_GTP is not set
# CONFIG_MACSEC is not set
# CONFIG_NETCONSOLE is not set
CONFIG_TUN=m
# CONFIG_TUN_VNET_CROSS_LE is not set
# CONFIG_VETH is not set
# CONFIG_NLMON is not set
# CONFIG_ARCNET is not set
#
@ -2986,6 +3004,7 @@ CONFIG_VIDEO_RK_IRCUT=y
# CONFIG_VIDEO_VS6624 is not set
# CONFIG_VIDEO_MIS2031 is not set
# CONFIG_VIDEO_MIS4001 is not set
# CONFIG_VIDEO_MIS5001 is not set
# CONFIG_VIDEO_MT9M001 is not set
# CONFIG_VIDEO_MT9M032 is not set
# CONFIG_VIDEO_MT9M111 is not set