mirror of
https://github.com/gtxaspec/wz_mini_hacks.git
synced 2025-12-02 05:58:15 +00:00
Merge branch 'gtxaspec:master' into master
This commit is contained in:
@@ -16,6 +16,7 @@ echo "CAR: c: reverse right"
|
||||
echo "CAR: x: all stop"
|
||||
echo "CAR: h: headlight on/off"
|
||||
echo "CAR: j: irled on/off"
|
||||
echo "CAR: b: honk"
|
||||
echo -e ""
|
||||
echo "CAR: 1: quit ASAP!"
|
||||
echo -e ""
|
||||
@@ -133,6 +134,12 @@ elif [ "$input" = "h" ]; then
|
||||
elif [ "$input" = "j" ]; then
|
||||
irled
|
||||
|
||||
elif [ "$input" = "x" ]; then
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\x80\x00\x02\x71" > /dev/ttyUSB0
|
||||
|
||||
elif [ "$input" = "b" ]; then
|
||||
/opt/wz_mini/bin/cmd aplay /opt/wz_mini/usr/share/audio/honk.wav 70 > /dev/null 2>&1 &
|
||||
|
||||
elif [ "$input" = "1" ]; then
|
||||
#exit
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\x80\x00\x02\x71" > /dev/ttyUSB0
|
||||
|
||||
Binary file not shown.
@@ -55,6 +55,8 @@ cp /system/bin/app.ver /opt/wz_mini/tmp/log_gather/system_app.ver
|
||||
echo "gather mmc info"
|
||||
cat /sys/bus/mmc/devices/mmc1\:0001/mmc1\:0001\:1/* > /opt/wz_mini/tmp/log_gather/mmc_sys.log
|
||||
|
||||
echo "gather lsusb"
|
||||
lsusb > /opt/wz_mini/tmp/log_gather/lsusb.log
|
||||
|
||||
if [ -f /tmp/sd_check_result.txt ]; then
|
||||
echo "copy sd_check_result.txt"
|
||||
|
||||
3
SD_ROOT/wz_mini/bin/wz_mini_edit.sh
Normal file
3
SD_ROOT/wz_mini/bin/wz_mini_edit.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
nano /opt/wz_mini/wz_mini.conf
|
||||
@@ -8,8 +8,10 @@ domain-needed
|
||||
bogus-priv
|
||||
dns-forward-max=150
|
||||
cache-size=1000
|
||||
min-cache-ttl=86400
|
||||
neg-ttl=3600
|
||||
no-poll
|
||||
resolv-file=/opt/wz_mini/etc/resolv.dnsmasq
|
||||
addn-hosts=/opt/wz_mini/etc/hosts
|
||||
#log-facility=-
|
||||
#log-queries
|
||||
|
||||
1
SD_ROOT/wz_mini/etc/hosts
Normal file
1
SD_ROOT/wz_mini/etc/hosts
Normal file
@@ -0,0 +1 @@
|
||||
127.0.0.1 localhost
|
||||
@@ -48,18 +48,62 @@ wait_wlan() {
|
||||
##Check if the driver has been loaded for the onboard wlan0, store the MAC.
|
||||
while true
|
||||
do
|
||||
if ifconfig wlan0 | grep "inet addr"; then
|
||||
if ifconfig wlan0 | grep "HWaddr"; then
|
||||
echo "wlan0 hwaddr is up"
|
||||
store_mac
|
||||
break
|
||||
elif ifconfig wlan0 | grep "inet addr" && [[ "$ENABLE_USB_ETH" == "true" || "$ENABLE_USB_DIRECT" == "true" ]]; then
|
||||
store_mac
|
||||
break
|
||||
fi
|
||||
echo " wlan0 not ready yet..."
|
||||
else
|
||||
echo "wlan0 hwaddr not ready yet..."
|
||||
sleep 5
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
wpa_check() {
|
||||
##Check if wpa_supplicant has been created by iCamera
|
||||
if [ -e /tmp/wpa_supplicant.conf ]; then
|
||||
wait_wlan
|
||||
echo "wpa_supplicant.conf ready"
|
||||
else
|
||||
echo "wpa_supplicant.conf not ready, wait some time for creation."
|
||||
COUNT=0
|
||||
ATTEMPTS=15
|
||||
until [[ -e /tmp/wpa_supplicant.conf ]] || [[ $COUNT -eq $ATTEMPTS ]]; do
|
||||
echo -e "$(( COUNT++ ))... \c"
|
||||
sleep 5
|
||||
wpa_check
|
||||
done
|
||||
if [[ $COUNT -eq $ATTEMPTS ]]; then
|
||||
echo "time exceeded waiting for iCamera, continue potentially broken condition without network."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
wlanold_check() {
|
||||
#Have we renamed interfaces yet?
|
||||
if [ -d /sys/class/net/wlanold ]; then
|
||||
echo "wlanold exist"
|
||||
eth_wlan_up
|
||||
else
|
||||
echo "wlanold doesn't exist"
|
||||
if [[ "$BONDING_ENABLED" == "true" ]] && ([[ "$ENABLE_USB_ETH" == "true" ]] || [[ "$ENABLE_USB_DIRECT" == "true" ]]); then
|
||||
rename_interface_and_setup_bonding bond0 "$BONDING_PRIMARY_INTERFACE" "$BONDING_SECONDARY_INTERFACE"
|
||||
else
|
||||
rename_interface $1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
netloop() {
|
||||
##While loop for check
|
||||
while true
|
||||
do
|
||||
wlanold_check $1
|
||||
echo "wlan0 not ready yet..."
|
||||
sleep 5
|
||||
done
|
||||
}
|
||||
|
||||
rename_interface() {
|
||||
##Fool iCamera by renaming the hardline interface to wlan0
|
||||
echo "renaming interfaces"
|
||||
@@ -166,48 +210,6 @@ eth_wlan_up() {
|
||||
break
|
||||
}
|
||||
|
||||
wpa_check() {
|
||||
#Check if wpa_supplicant has been created by iCamera
|
||||
if [ -e /tmp/wpa_supplicant.conf ]; then
|
||||
echo "wpa_supplicant.conf ready"
|
||||
wlanold_check $1
|
||||
else
|
||||
echo "wpa_supplicant.conf not ready, wait some time for creation."
|
||||
COUNT=0
|
||||
ATTEMPTS=15
|
||||
until [[ -e /tmp/wpa_supplicant.conf ]] || [[ $COUNT -eq $ATTEMPTS ]]; do
|
||||
echo -e "$(( COUNT++ ))... \c"
|
||||
sleep 5
|
||||
done
|
||||
[[ $COUNT -eq $ATTEMPTS ]] && echo "time exceeded waiting for iCamera, continue potentially broken condition without network." && wlanold_check $1
|
||||
fi
|
||||
}
|
||||
|
||||
wlanold_check() {
|
||||
#Have we renamed interfaces yet?
|
||||
if [ -d /sys/class/net/wlanold ]; then
|
||||
echo "wlanold exist"
|
||||
eth_wlan_up
|
||||
else
|
||||
echo "wlanold doesn't exist"
|
||||
if [[ "$BONDING_ENABLED" == "true" ]] && ([[ "$ENABLE_USB_ETH" == "true" ]] || [[ "$ENABLE_USB_DIRECT" == "true" ]]); then
|
||||
rename_interface_and_setup_bonding bond0 "$BONDING_PRIMARY_INTERFACE" "$BONDING_SECONDARY_INTERFACE"
|
||||
else
|
||||
rename_interface $1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
netloop() {
|
||||
##While loop for check
|
||||
while true
|
||||
do
|
||||
wpa_check $1
|
||||
echo "wlan0 not ready yet..."
|
||||
sleep 5
|
||||
done
|
||||
}
|
||||
|
||||
swap_enable() {
|
||||
if [ -e /opt/wz_mini/swap ]; then
|
||||
echo "Swap file exists"
|
||||
@@ -249,7 +251,7 @@ done
|
||||
}
|
||||
|
||||
first_run_check
|
||||
wait_wlan
|
||||
wpa_check
|
||||
|
||||
#Set module dir depending on platform
|
||||
if [ -f /opt/wz_mini/tmp/.T20 ]; then
|
||||
@@ -383,13 +385,8 @@ if [[ "$ENABLE_USB_DIRECT" == "true" ]]; then
|
||||
|
||||
swap_enable
|
||||
|
||||
#loop begin
|
||||
while true
|
||||
do
|
||||
wpa_check usb0
|
||||
echo "wlan0 not ready yet..."
|
||||
sleep 1
|
||||
done
|
||||
netloop usb0
|
||||
|
||||
else
|
||||
echo "USB Direct disabled"
|
||||
fi
|
||||
@@ -407,13 +404,8 @@ if [[ "$ENABLE_USB_RNDIS" == "true" ]]; then
|
||||
|
||||
swap_enable
|
||||
|
||||
#loop begin
|
||||
while true
|
||||
do
|
||||
wpa_check usb0
|
||||
echo "wlan0 not ready yet..."
|
||||
sleep 1
|
||||
done
|
||||
netloop usb0
|
||||
|
||||
fi
|
||||
else
|
||||
echo "usb rndis disabled"
|
||||
@@ -593,6 +585,16 @@ if [[ "$NIGHT_DROP_DISABLE" == "true" ]]; then
|
||||
touch /opt/wz_mini/tmp/.nd
|
||||
fi
|
||||
|
||||
if [[ "$ENABLE_LOCAL_DNS" == "true" ]]; then
|
||||
dnsmasq -C /opt/wz_mini/etc/dnsmasq.conf
|
||||
rm -f /tmp/resolv.conf
|
||||
cp /opt/wz_mini/etc/resolv.conf /tmp/resolv.conf
|
||||
fi
|
||||
|
||||
if [[ "$WEB_SERVER_ENABLED" == "true" ]]; then
|
||||
httpd -p 80 -h /opt/wz_mini/www
|
||||
fi
|
||||
|
||||
hostname_set
|
||||
touch /opt/wz_mini/tmp/.wz_user_firstrun
|
||||
pkill -f dumpload #Kill dumpload so it won't waste cpu or ram gathering cores and uploading them when something crashes
|
||||
|
||||
1
SD_ROOT/wz_mini/etc/passwd
Normal file
1
SD_ROOT/wz_mini/etc/passwd
Normal file
@@ -0,0 +1 @@
|
||||
root:x:0:0:root:/opt/wz_mini/root:/bin/sh
|
||||
1
SD_ROOT/wz_mini/etc/resolv.conf
Normal file
1
SD_ROOT/wz_mini/etc/resolv.conf
Normal file
@@ -0,0 +1 @@
|
||||
nameserver 127.0.0.1
|
||||
@@ -1,4 +1,4 @@
|
||||
#List your desired upstream dns servers here
|
||||
|
||||
#nameserver 8.8.8.8
|
||||
#nameserver 8.8.4.4
|
||||
nameserver 1.1.1.1
|
||||
nameserver 1.0.0.1
|
||||
|
||||
@@ -92,6 +92,7 @@ NIGHT_DROP_DISABLE="false"
|
||||
DISABLE_MOTOR="false"
|
||||
ENABLE_FSCK_ON_BOOT="false"
|
||||
ENABLE_CAR_DRIVER="false"
|
||||
ENABLE_LOCAL_DNS="false"
|
||||
|
||||
#####DEBUG#####
|
||||
#drops you to a shell via serial, doesn't load app_init.sh
|
||||
@@ -99,5 +100,8 @@ DEBUG_ENABLED="false"
|
||||
DEBUG_INITRAMFS_ENABLED="false"
|
||||
DEBUG_PASSWORD="false"
|
||||
|
||||
####WEB####
|
||||
WEB_SERVER_ENABLED="false"
|
||||
|
||||
#####SCRIPTING#####
|
||||
CUSTOM_SCRIPT_PATH=""
|
||||
|
||||
@@ -1 +1 @@
|
||||
Fri Jul 15 11:46:04 AM PDT 2022
|
||||
Tue Jul 26 07:57:02 AM PDT 2022
|
||||
|
||||
BIN
SD_ROOT/wz_mini/usr/share/audio/honk.wav
Normal file
BIN
SD_ROOT/wz_mini/usr/share/audio/honk.wav
Normal file
Binary file not shown.
31
SD_ROOT/wz_mini/www/car/car.css
Normal file
31
SD_ROOT/wz_mini/www/car/car.css
Normal file
@@ -0,0 +1,31 @@
|
||||
.wz_car_BUTTON {
|
||||
background-color: #4CAF50; /* Green */
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 15px 32px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
margin: 4px 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.wz_car_BUTTON_N {
|
||||
background-color: #4CAF50; /* Green */
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 15px 32px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
margin: 4px 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.wz_car_TABLE {
|
||||
width: 55%;
|
||||
border-collapse: collapse;
|
||||
float: left;
|
||||
}
|
||||
57
SD_ROOT/wz_mini/www/car/car.html
Normal file
57
SD_ROOT/wz_mini/www/car/car.html
Normal file
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="car.js"></script>
|
||||
<link rel="stylesheet" href="car.css">
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h2>wz_mini Car Control</h2>
|
||||
|
||||
<table class="wz_car_TABLE" border="1">
|
||||
<tbody>
|
||||
<tr style="height: 21px;">
|
||||
<td style="width: 33.3333%; height: 21px; text-align: left;"><button id="forward_left" class="wz_car_BUTTON">q: forward left</button></td>
|
||||
<td style="width: 33.3333%; height: 21px; text-align: center;"><button id="forward" class="wz_car_BUTTON">w: forward</button></td>
|
||||
<td style="width: 33.3333%; height: 21px; text-align: right;"><button id="forward_right" class="wz_car_BUTTON">e: forward right</button></td>
|
||||
</tr>
|
||||
<tr style="height: 18px;">
|
||||
<td style="width: 33.3333%; height: 18px; text-align: left;"><button id="left" class="wz_car_BUTTON">a; left</button></td>
|
||||
<td style="width: 33.3333%; height: 18px; text-align: center;"><button id="reverse" class="wz_car_BUTTON">s: rear</button></td>
|
||||
<td style="width: 33.3333%; height: 18px; text-align: right;"><button id="right" class="wz_car_BUTTON">d: right</button></td>
|
||||
</tr>
|
||||
<tr style="height: 18px;">
|
||||
<td style="width: 33.3333%; height: 18px; text-align: left;"><button id="reverse_left" class="wz_car_BUTTON">z: rear left</button></td>
|
||||
<td style="width: 33.3333%; height: 18px; text-align: center;"><button id="all_stop" class="wz_car_BUTTON">x: all stop</button></td>
|
||||
<td style="width: 33.3333%; height: 18px; text-align: right;"><button id="reverse_right" class="wz_car_BUTTON">c: rear right</button></td>
|
||||
</tr>
|
||||
<td style="width: 33.3333%; height: 18px; text-align: center;">
|
||||
<button id="headlight_on" class="wz_car_BUTTON_N">h: headlight on</button>
|
||||
<button id="headlight_off" class="wz_car_BUTTON_N">g: headlight off</button>
|
||||
</td>
|
||||
<td style="width: 33.3333%; height: 18px; text-align: center;"><button id="irled_on" class="wz_car_BUTTON">j: ir led on</button><button id="irled_off" class="wz_car_BUTTON">k: ir led off</button></td>
|
||||
<td style="width: 33.3333%; height: 18px; text-align: right;"><button id="honk" class="wz_car_BUTTON">b: honk</button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p><img id="car_feed" src="/cgi-bin/jpeg.cgi?channel=1" /></p>
|
||||
|
||||
Speed Sleep: <input type="text" size=5 id="sleep_timer" name="sleep_timer" value="0.15">
|
||||
|
||||
Car Speed:
|
||||
|
||||
<input type="radio" id="speed_fast" class="speed" name="fast" value="fast">
|
||||
<label for="fast">Fast</label>
|
||||
|
||||
<input type="radio" id="speed_slow" class="speed" name="slow" value="slow">
|
||||
<label for="slow">Slow</label>
|
||||
|
||||
<button onclick="set_vars()">Set Variables</button>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
77
SD_ROOT/wz_mini/www/car/car.js
Normal file
77
SD_ROOT/wz_mini/www/car/car.js
Normal file
@@ -0,0 +1,77 @@
|
||||
const queryString = window.location.search;
|
||||
console.log(queryString);
|
||||
const urlParams = new URLSearchParams(queryString);
|
||||
|
||||
const speed = urlParams.get('speed')
|
||||
console.log("speed is", speed);
|
||||
|
||||
const sleep_timer = urlParams.get('sleep_time')
|
||||
console.log("sleep_timer is", sleep_timer);
|
||||
|
||||
function set_sleep() {
|
||||
sleep_timer2 = document.getElementById("sleep_timer").value;
|
||||
window.location = "car.html?sleep_time=" + sleep_timer2;
|
||||
}
|
||||
|
||||
function set_vars() {
|
||||
sleep_timer2 = document.getElementById("sleep_timer").value;
|
||||
var speed = $('input[class="speed"]:checked').val();
|
||||
|
||||
window.location = "car.html?sleep_time=" + sleep_timer2 + "&speed=" + speed;
|
||||
}
|
||||
|
||||
|
||||
var wz_mini_car = {
|
||||
post: function(action)
|
||||
{
|
||||
$.post( "../cgi-bin/car.sh", { speed: speed, action: action, sleep_time: sleep_timer } );
|
||||
} ,
|
||||
init: function() {
|
||||
this.logarray = [];
|
||||
$("[class*='BUTTON']").on('click',function(e) {
|
||||
var action = $(this).attr('id');
|
||||
wz_mini_car.post(action);
|
||||
});
|
||||
|
||||
/* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch
|
||||
switch is strict
|
||||
*/
|
||||
|
||||
addEventListener("keydown", function (e) {
|
||||
var action = false;
|
||||
switch(e.key) {
|
||||
case "w": action = "forward"; break;
|
||||
case "s": action = "reverse"; break;
|
||||
case "a": action = "left"; break;
|
||||
case "d": action = "right"; break;
|
||||
case "q": action = "forward_left" ; break;
|
||||
case "e": action = "forward_right"; break;
|
||||
case "z": action = "reverse_left"; break;
|
||||
case "c": action = "reverse_right" ; break;
|
||||
case "x": action = "all_stop" ; break;
|
||||
case "h": action = "headlight_on" ; break;
|
||||
case "g": action = "headlight_off" ; break;
|
||||
case "j": action = "irled_on" ; break;
|
||||
case "k": action = "irled_off" ; break;
|
||||
case "b": action = "honk" ; break;
|
||||
}
|
||||
if (action) {
|
||||
wz_mini_car.post(action);
|
||||
}
|
||||
});
|
||||
},
|
||||
log: function(text)
|
||||
{
|
||||
this.logarray.push(text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
wz_mini_car.init();
|
||||
});
|
||||
|
||||
setInterval(function() {
|
||||
var myImageElement = document.getElementById('car_feed');
|
||||
myImageElement.src = '/cgi-bin/jpeg.cgi?channel=1&rand=' + Math.random();
|
||||
}, 1000);
|
||||
23
SD_ROOT/wz_mini/www/cgi-bin/BONDING_ENABLED.md
Normal file
23
SD_ROOT/wz_mini/www/cgi-bin/BONDING_ENABLED.md
Normal file
@@ -0,0 +1,23 @@
|
||||
Network Interface Bonding Support
|
||||
|
||||
BONDING_ENABLED="false"
|
||||
BONDING_PRIMARY_INTERFACE="eth0"
|
||||
BONDING_SECONDARY_INTERFACE="wlan0"
|
||||
BONDING_LINK_MONITORING_FREQ_MS="100"
|
||||
BONDING_DOWN_DELAY_MS="5000"
|
||||
BONDING_UP_DELAY_MS="5000"
|
||||
Bonding description is best described here: https://wiki.debian.org/Bonding#Configuration_-_Example_2_.28.22Laptop-Mode.22.29:
|
||||
|
||||
("Laptop-Mode")
|
||||
|
||||
Tie cable and wireless network interfaces (RJ45/WLAN) together to define a single, virtual (i.e. bonding) network interface (e.g. bond0). As long as the network cable is connected, its interface (e.g. eth0) is used for the network traffic. If you pull the RJ45-plug, ifenslave switches over to the wireless interface (e.g. wlan0) transparently, without any loss of network packages. After reconnecting the network cable, ifenslave switches back to eth0 ("failover mode"). From the outside (=network) view it doesn't matter which interface is active. The bonding device presents its own software-defined (i.e. virtual) MAC address, different from the hardware defined MACs of eth0 or wlan0. The dhcp server will use this MAC to assign an ip address to the bond0 device. So the computer has one unique ip address under which it can be identified. Without bonding each interface would have its own ip address. Currenly supported with ethernet adapters and usb-direct mode.
|
||||
|
||||
BONDING_PRIMARY_INTERFACE Specifies the interface that should be the primary. Typically "eth0".
|
||||
|
||||
BONDING_SECONDARY_INTERFACE Specifies the interface that should be the secondary. Typically "wlan0".
|
||||
|
||||
BONDING_LINK_MONITORING_FREQ_MS Specifies the MII link monitoring frequency in milliseconds. This determines how often the link state of each slave is inspected for link failures.
|
||||
|
||||
BONDING_DOWN_DELAY_MS Specifies the time, in milliseconds, to wait before disabling a slave after a link failure has been detected. This option is only valid for the miimon link monitor. The downdelay value should be a multiple of the miimon value; if not, it will be rounded down to the nearest multiple.
|
||||
|
||||
BONDING_UP_DELAY_MS Specifies the time, in milliseconds, to wait before enabling a slave after a link recovery has been detected. This option is only valid for the miimon link monitor. The updelay value should be a multiple of the miimon value; if not, it will be rounded down to the nearest multiple.
|
||||
4
SD_ROOT/wz_mini/www/cgi-bin/DISABLE_FW_UPGRADE.md
Normal file
4
SD_ROOT/wz_mini/www/cgi-bin/DISABLE_FW_UPGRADE.md
Normal file
@@ -0,0 +1,4 @@
|
||||
If a remote or app update is initiated, the camera will reboot due to the failure of the update. The firmware update should not proceed again for some time, or at all.
|
||||
|
||||
When a firmware update is initiated, due to a bootloader issue (bug?), we intercept the update process and flash it manually. This should now result in a successful update, if it doesn't, please restore the unit's firmware manually using demo_wcv3.bin on the micro sd card.
|
||||
|
||||
4
SD_ROOT/wz_mini/www/cgi-bin/ENABLE_MP4_WRITE.md
Normal file
4
SD_ROOT/wz_mini/www/cgi-bin/ENABLE_MP4_WRITE.md
Normal file
@@ -0,0 +1,4 @@
|
||||
ENABLE_MP4_WRITE="false"
|
||||
Forces the camera to skip writing files to /tmp, and write them directly to your storage medium or network mount, prevents trashing. Normally videos are written to /tmp then moved using mv, which can overload camera and or remote network connections. Useful for NFS/CIFS remote video storage.
|
||||
|
||||
|
||||
5
SD_ROOT/wz_mini/www/cgi-bin/ENABLE_USB_DIRECT.md
Normal file
5
SD_ROOT/wz_mini/www/cgi-bin/ENABLE_USB_DIRECT.md
Normal file
@@ -0,0 +1,5 @@
|
||||
the next time you boot your camera, make sure your USB cable is connected to the router. Remember, the camera has to be setup initially with Wi-Fi for this to work. After setup, Wi-Fi is no longer needed. Note that using USB Direct disables the onboard Wi-Fi. Change the MAC Address if you desire via USB_DIRECT_MAC_ADDR variable.
|
||||
|
||||
Connectivity is supported using a direct USB connection only... this means a single cable from the camera, to a supported host (An OpenWRT router, for example) that supports the usb-cdc-ncm specification. (NCM, not ECM) If you have an OpenWrt based router, install the kmod-usb-net-cdc-ncm package. The camera should automatically pull the IP from the router with most configurations. You can also use any modern linux distro to provide internet to the camera, provided it supports CDC_NCM. enjoy!
|
||||
|
||||
Note: In my testing, the micro-usb cables included with the various cameras do not pass data, so they will not work. Make sure you have a micro-usb cable that passes data!
|
||||
13
SD_ROOT/wz_mini/www/cgi-bin/ENABLE_USB_ETH.md
Normal file
13
SD_ROOT/wz_mini/www/cgi-bin/ENABLE_USB_ETH.md
Normal file
@@ -0,0 +1,13 @@
|
||||
USB Ethernet Adapter support:
|
||||
|
||||
ENABLE_USB_ETH="true"
|
||||
ENABLE_USB_ETH_MODULE_AUTODETECT="true"
|
||||
ENABLE_USB_ETH_MODULE_MANUAL=""
|
||||
To have the Ethernet NIC be auto-detected and loaded automatically, set the ENABLE_USB_ETH_MODULE_AUTODETECT value to true.
|
||||
|
||||
To load a specific USB Ethernet NIC driver, set ENABLE_USB_ETH_MODULE_MANUAL to one of the following: asix, ax88179_178a, cdc_ether, r8152
|
||||
|
||||
NOTE: There is a possibility of a conflict between Ethernet NIC adapters that report themselves as PCI ID '0bda:8152'. (Realtek 8152 and CDC Ethernet) Since the 8152 is Realtek's product, that driver will be the one used for products that report that PCI ID. If you happen to have a CDC Ethernet product that uses that specific PCI ID, please set the ENABLE_USB_ETH_MODULE_AUTODETECT option to false, and set ENABLE_USB_ETH_MODULE_MANUAL to "cdc_ether"
|
||||
|
||||
The next time you boot your camera, make sure your USB Ethernet Adapter is connected to the camera and ethernet. The camera has to be setup initially with Wi-Fi for this to work. After setup, Wi-Fi is no longer needed, as long as you are using the USB Ethernet Adapter. Note that using USB Ethernet disables the onboard Wi-Fi.
|
||||
|
||||
6
SD_ROOT/wz_mini/www/cgi-bin/ENABLE_USB_STORAGE.md
Normal file
6
SD_ROOT/wz_mini/www/cgi-bin/ENABLE_USB_STORAGE.md
Normal file
@@ -0,0 +1,6 @@
|
||||
USB Mass Storage Support:
|
||||
|
||||
ENABLE_USB_STORAGE="true"
|
||||
If you would like to mount an EXT3/4 filesystem, also change:
|
||||
|
||||
ENABLE_EXT4="true"
|
||||
19
SD_ROOT/wz_mini/www/cgi-bin/ENABLE_WIREGUARD.md
Normal file
19
SD_ROOT/wz_mini/www/cgi-bin/ENABLE_WIREGUARD.md
Normal file
@@ -0,0 +1,19 @@
|
||||
Wireguard support is available as a kernel module:
|
||||
|
||||
ENABLE_WIREGUARD="true"
|
||||
Use the command wg to setup. See https://www.wireguard.com/quickstart/ for more info.
|
||||
|
||||
Some users have asked about tailscale support, I have tested and it works. See the issue #30 for further information.
|
||||
|
||||
Example setup:
|
||||
|
||||
ENABLE_WIREGUARD="true"
|
||||
WIREGUARD_IPV4="192.168.2.101/32"
|
||||
WIREGUARD_PEER_ENDPOINT="x.x.x.x:51820"
|
||||
WIREGUARD_PEER_PUBLIC_KEY="INSERT_PEER_PUBLIC_KEY_HERE"
|
||||
WIREGUARD_PEER_ALLOWED_IPS="192.168.2.0/24"
|
||||
WIREGUARD_PEER_KEEP_ALIVE="25"
|
||||
To retrieve the public key that you'll need to add the peer to your wireguard endpoint:
|
||||
|
||||
Use SSH to log in
|
||||
wg
|
||||
8
SD_ROOT/wz_mini/www/cgi-bin/REMOTE_SPOTLIGHT.md
Normal file
8
SD_ROOT/wz_mini/www/cgi-bin/REMOTE_SPOTLIGHT.md
Normal file
@@ -0,0 +1,8 @@
|
||||
When USB Direct connectivity is enabled, the camera will be unable to communicate with accessories. To enable remote spotlight accessory support, enable the following variable and set the IP Address of the host as follows:
|
||||
|
||||
REMOTE_SPOTLIGHT="true"
|
||||
REMOTE_SPOTLIGHT_HOST="0.0.0.0"
|
||||
Then, run the following command on the host where the spotlight is attached to:
|
||||
|
||||
socat TCP4-LISTEN:9000,reuseaddr,fork /dev/ttyUSB0,raw,echo=0
|
||||
Change /dev/ttyUSB0 to whatever path your spotlight enumerated to if necessary. The camera will now be able to control the spotlight.
|
||||
10
SD_ROOT/wz_mini/www/cgi-bin/RTMP_STREAM_ENABLED.md
Normal file
10
SD_ROOT/wz_mini/www/cgi-bin/RTMP_STREAM_ENABLED.md
Normal file
@@ -0,0 +1,10 @@
|
||||
RTMP Streaming:
|
||||
|
||||
RTMP_STREAM_ENABLED="true"
|
||||
RTMP_STREAM_FEED="video1_unicast"
|
||||
RMTP_STREAM_SERVICE="youtube"
|
||||
RTMP_STREAM_DISABLE_AUDIO="false"
|
||||
RTMP_STREAM_YOUTUBE_KEY="xxx-xxx-xxx-xxx"
|
||||
RTMP_STREAM_TWITCH_KEY=""
|
||||
RTMP_STREAM_FACEBOOK_KEY=""
|
||||
Live stream DIRECTLY from the camera's local RTSP server to: youtube / twitch / facebook live. Audio must be enabled in the RTSP section of the configuration for this to work.
|
||||
25
SD_ROOT/wz_mini/www/cgi-bin/RTSP_HI_RES_ENABLED.md
Normal file
25
SD_ROOT/wz_mini/www/cgi-bin/RTSP_HI_RES_ENABLED.md
Normal file
@@ -0,0 +1,25 @@
|
||||
RTSP streaming: The RTSP server supports the two video streams provided by the camera, 1080p/360p (1296p/480p for the DB3). You can choose to enable a single stream of your choice, or both. Audio is also available. Set your login credentials here, server listening port, and the stream bitrate. (ENC_PARAMETER variable accepts numbers only. 0=FIXQP, 1=CBR, 2=VBR, 4=CAPPED VBR, 8=CAPPED QUALITY. Currently only 2, 4, and 8 are working)
|
||||
|
||||
RTSP_LOGIN="admin"
|
||||
RTSP_PASSWORD=""
|
||||
RTSP_PORT="8554"
|
||||
|
||||
RTSP_HI_RES_ENABLED="true"
|
||||
RTSP_HI_RES_ENABLE_AUDIO="true"
|
||||
RTSP_HI_RES_MAX_BITRATE="2048"
|
||||
RTSP_HI_RES_TARGET_BITRATE="1024"
|
||||
RTSP_HI_RES_ENC_PARAMETER="2"
|
||||
RTSP_HI_RES_FPS="15"
|
||||
|
||||
RTSP_LOW_RES_ENABLED="false"
|
||||
RTSP_LOW_RES_ENABLE_AUDIO="false"
|
||||
RTSP_LOW_RES_MAX_BITRATE=""
|
||||
RTSP_LOW_RES_TARGET_BITRATE=""
|
||||
RTSP_LOW_RES_ENC_PARAMETER=""
|
||||
RTSP_LOW_RES_FPS=""
|
||||
|
||||
the singular stream will be located at rtsp://login:password@IP_ADDRESS:8554/unicast multiple streams are located at rtsp://login:password@IP_ADDRESS:8554/video1_unicast and rtsp://login:password@IP_ADDRESS:8554/video2_unicast
|
||||
|
||||
Note: If you don't set the password, the password will be set to the unique MAC address of the camera, in all uppercase, including the colons... for example:. AA:BB:CC:00:11:22. It's typically printed on the camera. Higher video bitrates may overload your Wi-Fi connection, so a wired connection is recommended.
|
||||
|
||||
Huge credit to @mnakada for his libcallback library: https://github.com/mnakada/atomcam_tools
|
||||
7
SD_ROOT/wz_mini/www/cgi-bin/WEB_CAM_ENABLE.md
Normal file
7
SD_ROOT/wz_mini/www/cgi-bin/WEB_CAM_ENABLE.md
Normal file
@@ -0,0 +1,7 @@
|
||||
Use as a USB Video Class (UVC) Web Camera for your PC is supported. I have tested with Windows 10, Linux, and Android TV, and it appears as a Generic HD Camera. Audio is supported. This mode disables all other functionality, and only works as a USB Web Camera for your PC. Experimental. Note that the cables typically included with the camera do not data, use a known working micro-usb cable which supports data.
|
||||
|
||||
Supported modes: MJPG,Video 360p/720p/1080p
|
||||
|
||||
WEB_CAM_ENABLE="true"
|
||||
WEB_CAM_BIT_RATE="8000"
|
||||
WEB_CAM_FPS_RATE="25"
|
||||
95
SD_ROOT/wz_mini/www/cgi-bin/car.sh
Normal file
95
SD_ROOT/wz_mini/www/cgi-bin/car.sh
Normal file
@@ -0,0 +1,95 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
|
||||
echo "HTTP/1.1 200"
|
||||
echo -e "Content-type: text/html\n\n"
|
||||
echo ""
|
||||
|
||||
read POST_STRING
|
||||
|
||||
SPEED=$(echo $POST_STRING | sed 's/.*speed=//;s/\&.*//')
|
||||
ACTION=$(echo $POST_STRING | sed 's/.*action=//;s/\&.*//')
|
||||
SLEEP_TIME=$(echo $POST_STRING | sed 's/.*sleep_time=//;s/\&.*//')
|
||||
|
||||
echo "raw post string: $POST_STRING"
|
||||
echo "speed: $SPEED"
|
||||
echo "action: $ACTION"
|
||||
echo "sleep: $SLEEP_TIME"
|
||||
|
||||
if [ "$ACTION" = "forward" ]; then
|
||||
|
||||
if [ "$SPEED" = "slow" ]; then
|
||||
echo "slow"
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\xca\x00\x02\xbb" > /dev/ttyUSB0
|
||||
else
|
||||
echo "forward"
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\xe3\x00\x02\xd4" > /dev/ttyUSB0
|
||||
fi
|
||||
|
||||
sleep $SLEEP_TIME
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\x80\x00\x02\x71" > /dev/ttyUSB0
|
||||
|
||||
elif [ "$ACTION" = "reverse" ]; then
|
||||
echo "reverse"
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\x36\x00\x02\x27" > /dev/ttyUSB0
|
||||
|
||||
sleep $SLEEP_TIME
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\x80\x00\x02\x71" > /dev/ttyUSB0
|
||||
elif [ "$ACTION" = "left" ]; then
|
||||
echo "left"
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x76\x81\x00\x02\x68" > /dev/ttyUSB0
|
||||
|
||||
sleep $SLEEP_TIME
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\x80\x00\x02\x71" > /dev/ttyUSB0
|
||||
elif [ "$ACTION" = "right" ]; then
|
||||
echo "right"
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x8a\x81\x00\x02\x7c" > /dev/ttyUSB0
|
||||
|
||||
sleep $SLEEP_TIME
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\x80\x00\x02\x71" > /dev/ttyUSB0
|
||||
elif [ "$ACTION" = "forward_left" ]; then
|
||||
echo "left_forward"
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x76\xe3\x00\x02\xca" > /dev/ttyUSB0
|
||||
|
||||
sleep $SLEEP_TIME
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\x80\x00\x02\x71" > /dev/ttyUSB0
|
||||
elif [ "$ACTION" = "forward_right" ]; then
|
||||
echo "right_forward"
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x8a\xe3\x00\x02\xde" > /dev/ttyUSB0
|
||||
|
||||
sleep $SLEEP_TIME
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\x80\x00\x02\x71" > /dev/ttyUSB0
|
||||
elif [ "$ACTION" = "reverse_left" ]; then
|
||||
echo "left_reverse"
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x76\x36\x00\x02\x1d" > /dev/ttyUSB0
|
||||
sleep $SLEEP_TIME
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\x80\x00\x02\x71" > /dev/ttyUSB0
|
||||
elif [ "$ACTION" = "reverse_right" ]; then
|
||||
echo "right_reverse"
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x8a\x36\x00\x02\x31" > /dev/ttyUSB0
|
||||
sleep $SLEEP_TIME
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\x80\x00\x02\x71" > /dev/ttyUSB0
|
||||
elif [ "$ACTION" = "all_stop" ]; then
|
||||
echo "all stop"
|
||||
echo -ne "\xaa\x55\x43\x06\x29\x80\x80\x00\x02\x71" > /dev/ttyUSB0
|
||||
elif [ "$ACTION" = "headlight_on" ]; then
|
||||
echo "headlight_on"
|
||||
echo -ne "\xaa\x55\x43\x04\x1e\x01\x01\x65" > /dev/ttyUSB0
|
||||
elif [ "$ACTION" = "headlight_off" ]; then
|
||||
echo "headlight_off"
|
||||
echo -ne "\xaa\x55\x43\x04\x1e\x02\x01\x66" > /dev/ttyUSB0
|
||||
elif [ "$ACTION" = "irled_on" ]; then
|
||||
echo "irled_on"
|
||||
cmd irled on > /dev/null
|
||||
elif [ "$ACTION" = "irled_off" ]; then
|
||||
echo "irled_off"
|
||||
cmd irled off > /dev/null
|
||||
elif [ "$ACTION" = "honk" ]; then
|
||||
echo "honk"
|
||||
/opt/wz_mini/bin/cmd aplay /opt/wz_mini/usr/share/audio/honk.wav 70 > /dev/null 2>&1 &
|
||||
|
||||
|
||||
else
|
||||
echo "no input"
|
||||
fi
|
||||
290
SD_ROOT/wz_mini/www/cgi-bin/config.cgi
Normal file
290
SD_ROOT/wz_mini/www/cgi-bin/config.cgi
Normal file
@@ -0,0 +1,290 @@
|
||||
#!/bin/sh
|
||||
# This serves a rudimentary webpage based on wz_mini.conf
|
||||
base_dir=/opt/wz_mini/
|
||||
base_hack_ini=/opt/wz_mini/wz_mini.conf
|
||||
hack_ini=$base_hack_ini
|
||||
www_dir=/opt/wz_mini/www/cgi-bin/
|
||||
camver=V3
|
||||
camfirmware=$(tail -n1 /configs/app.ver | cut -f2 -d= )
|
||||
hackver=$(cat /opt/wz_mini/usr/bin/app.ver)
|
||||
title="Wyze $camver on $camfirmware running wz_mini $hackver as $HOSTNAME"
|
||||
updated=false
|
||||
|
||||
echo "HTTP/1.1 200"
|
||||
echo -e "Content-type: text/html\n\n"
|
||||
echo ""
|
||||
|
||||
|
||||
reboot_camera() {
|
||||
echo "rebooting camera (refreshing screen in 90 seconds)"
|
||||
echo '<script type="text/javascript">setTimeout(function(){ document.location.reload (); },90 * 1000)</script>'
|
||||
exit
|
||||
}
|
||||
|
||||
shft() {
|
||||
# SE loop did not work -- thanks ash!
|
||||
suff=8
|
||||
while [ "$suff" -gt 0 ] ;
|
||||
do
|
||||
if [[ -f "$1.$suff" ]] ; then
|
||||
nxt=$((suff + 1))
|
||||
mv -f "$1.$suff" "$1.$nxt"
|
||||
fi
|
||||
suff=$((suff-1))
|
||||
done
|
||||
mv -f "$1" "$1.1"
|
||||
}
|
||||
|
||||
|
||||
function revert_config
|
||||
{
|
||||
mv "$hack_ini" "$hack_ini.old"
|
||||
mv "$hack_ini.$1" "$hack_ini"
|
||||
}
|
||||
|
||||
|
||||
function revert_menu
|
||||
{
|
||||
echo '<h2 id="revert" >Revert Menu</a>'
|
||||
echo '<div class="old_configs">'
|
||||
echo 'Prior Versions : '
|
||||
xuff=0
|
||||
while [ "$xuff" -lt 9 ] ;
|
||||
do
|
||||
xuff=$((xuff + 1))
|
||||
if [[ -f "$1.$xuff" ]] ; then
|
||||
filedate=$(date -r "$1.$xuff" )
|
||||
class=""
|
||||
if [ "$1.$xuff" = "$2" ];
|
||||
then
|
||||
class="current_revert"
|
||||
fi
|
||||
echo '<div class="revert_DIV '$class'"><div><a href="?action=show_revert&version='"$xuff"'">'"$xuff </a></div><div> $filedate</div></div>"
|
||||
fi
|
||||
done
|
||||
echo '</div>'
|
||||
}
|
||||
|
||||
function version_info
|
||||
{
|
||||
echo "<div id='$1'>"
|
||||
echo "<div class='ver_DIV' vertype='Camera'>$camver</div>"
|
||||
echo "<div class='ver_DIV' vertype='Camera Firmware'>$camfirmware</div>"
|
||||
echo "<div class='ver_DIV' vertype='wz_mini'>$hackver</div>"
|
||||
echo "<div class='ver_DIV' vertype='Hostname'> $HOSTNAME</div>"
|
||||
echo "</div>"
|
||||
}
|
||||
|
||||
|
||||
|
||||
if [[ $REQUEST_METHOD = 'GET' ]]; then
|
||||
|
||||
#since ash does not handle arrays we create variables using eval
|
||||
IFS='&'
|
||||
for PAIR in $QUERY_STRING
|
||||
do
|
||||
K=$(echo $PAIR | cut -f1 -d=)
|
||||
VA=$(echo $PAIR | cut -f2 -d=)
|
||||
eval GET_$K=$VA
|
||||
done
|
||||
|
||||
if [[ "$GET_action" = "reboot" ]]; then
|
||||
reboot_camera
|
||||
fi
|
||||
if [[ "$GET_action" = "revert" ]]; then
|
||||
revert_config "$GET_version"
|
||||
fi
|
||||
if [[ "$GET_action" = "show_revert" ]]; then
|
||||
hack_ini="$hack_ini.$GET_version"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
#test for post
|
||||
if [[ $REQUEST_METHOD = 'POST' ]]; then
|
||||
if [ "$CONTENT_LENGTH" -gt 0 ]; then
|
||||
read -n $CONTENT_LENGTH POST_DATA <&0
|
||||
while read line
|
||||
do eval "echo ${line}"
|
||||
done
|
||||
fi
|
||||
|
||||
#since ash does not handle arrays we create variables using eval
|
||||
IFS='&'
|
||||
for PAIR in $POST_DATA
|
||||
do
|
||||
K=$(echo $PAIR | cut -f1 -d=)
|
||||
VA=$(echo $PAIR | cut -f2 -d=)
|
||||
VB=\"${VA//%3A/:}\"
|
||||
#echo "<div>$K=$VB</div>"
|
||||
eval POST_$K=\"$VB\"
|
||||
done
|
||||
|
||||
|
||||
#switch back to going through the config file
|
||||
output="$hack_ini.new"
|
||||
|
||||
#name our output file
|
||||
while IFS= read -r \ARGUMENT; do
|
||||
#cycle through each line of the current config
|
||||
#copy through all comments
|
||||
if [ -z "$ARGUMENT" ]; then
|
||||
echo -ne "\n" >> $output
|
||||
elif [[ ${ARGUMENT:0:1} == "#" ]] ; then
|
||||
#echo $ARGUMENT $'\n'
|
||||
echo -ne $ARGUMENT"\n" >> $output
|
||||
else
|
||||
#for non-comments check to see if we have an entry in the POST data by deciphering the key from the ini file and using eval for our fake array
|
||||
KEY=$(echo $ARGUMENT | cut -f1 -d=)
|
||||
test=$(eval echo \$POST_$KEY)
|
||||
#echo "key was $KEY test was ... $test <br /> "
|
||||
if [[ "$test" ]]; then
|
||||
#if in the fake array then we use the new value
|
||||
#echo "<div style=\"color:#c00\">matched </div>"
|
||||
echo -ne $KEY=\"$test\""\n" >> $output
|
||||
else
|
||||
#if not in the fake array we use the current value
|
||||
#echo "<div>key not found</div>"
|
||||
echo -ne $ARGUMENT"\n" >> $output
|
||||
fi
|
||||
|
||||
fi
|
||||
done < $hack_ini
|
||||
|
||||
shft $hack_ini
|
||||
mv $output $hack_ini
|
||||
updated=true
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
function documentation_to_html
|
||||
{
|
||||
if [[ -f "$www_dir$1.md" ]]; then
|
||||
printf '<div class="ii_explain"><pre>'
|
||||
cat "$web_dir$1.md"
|
||||
printf '</pre></div>'
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function ini_to_html_free
|
||||
{
|
||||
classes=""
|
||||
if [ "$1" = "USB_DIRECT_MAC_ADDR" ]; then
|
||||
classes=" mac_addr"
|
||||
fi
|
||||
if grep -q -wi "$1" numerics.txt; then
|
||||
classes=" numeric"
|
||||
fi
|
||||
printf '<div class="ii"><div class="ii_key_DIV">%s</div><div class="ii_value_DIV"><input class="ii_value'$classes'" type="text" name="%s" value="%s" /></div>' $1 $1 $2
|
||||
documentation_to_html $1
|
||||
printf '</div>'
|
||||
}
|
||||
|
||||
function ini_to_html_tf
|
||||
{
|
||||
printf '<div class="ii"><div class="ii_key_DIV">%s</div>' $1
|
||||
printf '<div class="ii_value_DIV">'
|
||||
if [[ "$2" == "true" ]]; then
|
||||
printf '<input class="ii_radio" type="radio" name="%s" value="true" checked="checked" /> True ' $1
|
||||
printf '<input class="ii_radio" type="radio" name="%s" value="false" /> False ' $1
|
||||
else
|
||||
printf '<input class="ii_radio" type="radio" name="%s" value="true" /> True ' $1
|
||||
printf '<input class="ii_radio" type="radio" name="%s" value="false" checked="checked" /> False ' $1
|
||||
|
||||
fi
|
||||
printf '</div>'
|
||||
documentation_to_html $1
|
||||
printf '</div>'
|
||||
}
|
||||
|
||||
#function to handle camera feed
|
||||
function html_cam_feed
|
||||
{
|
||||
printf '<img id="current_feed" src="/cgi-bin/jpeg.cgi?channel=1" class="feed" />'
|
||||
}
|
||||
|
||||
|
||||
|
||||
function handle_css
|
||||
{
|
||||
echo -ne "<style type=\"text/css\">"
|
||||
cat config.css
|
||||
echo -ne '</style>';
|
||||
}
|
||||
|
||||
|
||||
echo -ne "<html><head><title>$title</title>"
|
||||
handle_css wz_mini_web.css
|
||||
|
||||
echo '<script type="text/javascript" src="/config.js" ></script>'
|
||||
echo -ne "</head>"
|
||||
|
||||
echo -ne '<body>'
|
||||
echo -ne "<h1>$title</h1>";
|
||||
|
||||
|
||||
if [ "$updated" = true ];
|
||||
then
|
||||
echo '<div class="message_DIV">configuration file updated. <a href="?action=reboot">Reboot<a/> to use changes. Or <a href="#revert">Revert</a> to a prior configuration</div>';
|
||||
|
||||
fi
|
||||
|
||||
html_cam_feed
|
||||
|
||||
|
||||
if [ $base_hack_ini != $hack_ini ]; then
|
||||
|
||||
echo '<div><a href="?action=revert&version='$GET_version'">Revert</a> to this version</a></div>'
|
||||
fi
|
||||
|
||||
echo -ne '<form name="update_config" method="POST" enctype="application/x-www-form-urlencoded" >'
|
||||
|
||||
|
||||
CONFIG_BLOCK=0
|
||||
|
||||
while IFS= read -r ARGUMENT; do
|
||||
if [ -z "$ARGUMENT" ] ; then
|
||||
echo -ne ""
|
||||
elif [[ ${ARGUMENT:0:1} == "#" ]] ; then
|
||||
if [[ ${ARGUMENT:0:4} == "####" ]]; then
|
||||
if [ "$CONFIG_BLOCK" -gt 0 ]; then
|
||||
echo '</div>'
|
||||
fi
|
||||
CONFIG_BLOCK=$((CONFIG_BLOCK + 1))
|
||||
echo '<div class="ii_block" block_number="'$CONFIG_BLOCK'" >'
|
||||
BTITLE=${ARGUMENT//#/ }
|
||||
echo -ne '<div class="ii_block_name">'$BTITLE'</div>'
|
||||
else
|
||||
echo -ne '<div class="ii_info">'$ARGUMENT'</div>'
|
||||
fi
|
||||
else
|
||||
KEY=$(echo $ARGUMENT | cut -f1 -d=)
|
||||
VAL=$(echo $ARGUMENT | cut -f2 -d=)
|
||||
VALUE=${VAL//\"/}
|
||||
case "$VALUE" in
|
||||
"true") ini_to_html_tf $KEY $VALUE ;;
|
||||
"false") ini_to_html_tf $KEY $VALUE ;;
|
||||
*) ini_to_html_free $KEY $VALUE
|
||||
esac
|
||||
fi
|
||||
done < $hack_ini
|
||||
if [ "$CONFIG_BLOCK" -gt 0 ]; then
|
||||
echo '</div>'
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo -ne '<input type="submit" name="update" value="Update" />'
|
||||
echo -ne '</form>'
|
||||
|
||||
|
||||
revert_menu $base_hack_ini $hack_ini
|
||||
|
||||
|
||||
version_info "display_BAR"
|
||||
|
||||
echo -ne '</body></html>'
|
||||
145
SD_ROOT/wz_mini/www/cgi-bin/config.css
Normal file
145
SD_ROOT/wz_mini/www/cgi-bin/config.css
Normal file
@@ -0,0 +1,145 @@
|
||||
BODY {
|
||||
--feed_ratio: 2.5;
|
||||
--display_bar_height: 20px;
|
||||
--border-color: #ccc;
|
||||
padding-bottom: var(--display_bar_height);
|
||||
}
|
||||
H1 {
|
||||
background-color:blue;
|
||||
color:white;
|
||||
height:calc(108px * (var(--feed_ratio) - 1));
|
||||
margin-top:0;
|
||||
padding:5px;
|
||||
margin-bottom:108px;
|
||||
width:calc(100% - (192px * var(--feed_ratio)));
|
||||
}
|
||||
|
||||
.ii_block {
|
||||
border:3px solid var(--border-color);
|
||||
margin-bottom:5px;
|
||||
padding:2px;
|
||||
border-radius:3px;
|
||||
}
|
||||
.ii_block_name {
|
||||
background-color:var(--border-color);
|
||||
text-align:center;
|
||||
font-weight:bold;
|
||||
color:#fff;
|
||||
margin:-2px;
|
||||
margin-bottom:3px;
|
||||
}
|
||||
.ii_info {
|
||||
color:#333;
|
||||
}
|
||||
.ii {
|
||||
width:100%;
|
||||
position:relative;
|
||||
display:flex;
|
||||
}
|
||||
.ii_key_DIV {
|
||||
|
||||
flex:0 0 40vw;
|
||||
font-weight:bold;
|
||||
}
|
||||
.ii_value_DIV {
|
||||
flex: 0 0 40vw;
|
||||
text-align:right;
|
||||
}
|
||||
.ii_value {
|
||||
width:75%;
|
||||
}
|
||||
.feed {
|
||||
position:absolute;
|
||||
top:10px;
|
||||
right:0px;
|
||||
width:calc(192px * var(--feed_ratio));
|
||||
height:calc(108px * var(--feed_ratio));
|
||||
z-index:10;
|
||||
}
|
||||
.ii_explain {
|
||||
height:25px;
|
||||
overflow:hidden;
|
||||
width:25px;
|
||||
position:relative;
|
||||
}
|
||||
.ii_explain:hover {
|
||||
height: auto;
|
||||
position: absolute;
|
||||
left: 10%;
|
||||
width: 80%;
|
||||
border-radius: 3px;
|
||||
padding: 5px;
|
||||
background-color: #ccc;
|
||||
z-index: 10;
|
||||
border: 3px solid blue;
|
||||
font-family: monospace;
|
||||
white-space:pre-wrap;
|
||||
}
|
||||
.ii_explain:hover PRE {
|
||||
white-space:pre-wrap;
|
||||
}
|
||||
.ii_explain:hover:after {
|
||||
content:"";
|
||||
border:none;
|
||||
margin:0;
|
||||
padding:0;
|
||||
width:0;
|
||||
height:0;
|
||||
}
|
||||
.ii_explain:after {
|
||||
color:white;
|
||||
content:"?";
|
||||
text-align:center;
|
||||
background-color:blue;
|
||||
border:2px solid #ccc;
|
||||
border-radius:3px;
|
||||
padding-left:2px;
|
||||
padding-right:2px;
|
||||
position:absolute;
|
||||
left:0;
|
||||
top:0;
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.revert_DIV {
|
||||
display:flex;
|
||||
width:100%;
|
||||
}
|
||||
.revert_DIV DIV:nth-child(1) {
|
||||
width:30px;
|
||||
}
|
||||
.current_revert {
|
||||
background-color:#edf054;
|
||||
}
|
||||
|
||||
#display_BAR {
|
||||
position:fixed;
|
||||
bottom:0;
|
||||
background-color:blue;
|
||||
border-top:1px solid lightblue;
|
||||
color:#fff;
|
||||
display:flex;
|
||||
width:100%;
|
||||
height:var(--display_bar_height);
|
||||
}
|
||||
#display_BAR DIV {
|
||||
padding-right:15px;
|
||||
}
|
||||
.ver_DIV {
|
||||
padding-left:60px;
|
||||
min-width:120px;
|
||||
font-family:monospace;
|
||||
flex: 1 0 120px;
|
||||
}
|
||||
.ver_DIV:before {
|
||||
content:attr(vertype);
|
||||
font-weight:bold;
|
||||
padding-right:10px;
|
||||
}
|
||||
.ver_DIV[vertype="wz_mini"] {
|
||||
flex:1 0 400px;
|
||||
}
|
||||
.fail_val {
|
||||
background-color:#fcc;
|
||||
}
|
||||
29
SD_ROOT/wz_mini/www/cgi-bin/jpeg.cgi
Normal file
29
SD_ROOT/wz_mini/www/cgi-bin/jpeg.cgi
Normal file
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
|
||||
#test for jpeg
|
||||
if [[ $REQUEST_METHOD = 'GET' ]]; then
|
||||
|
||||
echo "entered GET"
|
||||
#since ash does not handle arrays we create variables using eval
|
||||
IFS='&'
|
||||
for PAIR in $QUERY_STRING
|
||||
do
|
||||
K=$(echo $PAIR | cut -f1 -d=)
|
||||
VA=$(echo $PAIR | cut -f2 -d=)
|
||||
#VB=${VA//%3A/:}
|
||||
#echo "<div>$K=$VA</div>"
|
||||
eval GET_$K=$VA
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -z "$GET_channel" ];
|
||||
then
|
||||
echo "X-Channel-Override: 0"
|
||||
GET_channel=0
|
||||
fi
|
||||
|
||||
echo "X-Channel: $GET_channel"
|
||||
|
||||
cmd jpeg "$GET_channel"
|
||||
|
||||
8
SD_ROOT/wz_mini/www/cgi-bin/numerics.txt
Normal file
8
SD_ROOT/wz_mini/www/cgi-bin/numerics.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
WEB_CAM_BIT_RATE
|
||||
WEB_CAM_FPS_RATE
|
||||
BONDING_LINK_MONITORING_FREQ_MS
|
||||
BONDING_DOWN_DELAY_MS
|
||||
BONDING_UP_DELAY_MS
|
||||
RTSP_PORT
|
||||
AUDIO_PROMPT_VOLUME
|
||||
|
||||
59
SD_ROOT/wz_mini/www/config.js
Normal file
59
SD_ROOT/wz_mini/www/config.js
Normal file
@@ -0,0 +1,59 @@
|
||||
|
||||
var feed_interval_frequency = 1000;
|
||||
var mac_re = /^[0-9a-f]{1,2}([\.:-])(?:[0-9a-f]{1,2}\1){4}[0-9a-f]{1,2}$/mi;
|
||||
|
||||
// https://stackoverflow.com/questions/14636536/how-to-check-if-a-variable-is-an-integer-in-javascript#14794066
|
||||
function isInt(value) {
|
||||
return !isNaN(value) &&
|
||||
parseInt(Number(value)) == value &&
|
||||
!isNaN(parseInt(value, 10));
|
||||
}
|
||||
|
||||
function scrollTop()
|
||||
{
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: "smooth"
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
window.onload = function()
|
||||
{
|
||||
var feed = document.getElementById("current_feed");
|
||||
function update_image()
|
||||
{
|
||||
feed.src = feed.src.split("&")[0] + "&load=" + new Date().getTime();
|
||||
}
|
||||
feed_interval = setInterval(update_image, feed_interval_frequency);
|
||||
|
||||
|
||||
document.querySelector('[name="update_config"]').addEventListener('submit',
|
||||
function(e){
|
||||
const mac_addrs = document.getElementsByClassName('mac_addr');
|
||||
for (let i=0; i < mac_addrs.length; i++) {
|
||||
mac_addrs[i].classList.remove("fail_val");
|
||||
if (mac_addrs[i].value == "") { continue; }
|
||||
if (!mac_re.test(mac_addrs[i].value)) {
|
||||
mac_addrs[i].classList.add("fail_val");
|
||||
scrollTop();
|
||||
console.log("failed on mac address test for " + mac_addrs[i].name + " for value " + mac_addrs[i].value);
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
const numerics = document.getElementsByClassName('numeric');
|
||||
for (let i=0; i < numerics.length; i++) {
|
||||
numerics[i].classList.remove("fail_val");
|
||||
if (numerics[i].value == "") { continue; }
|
||||
if (!isInt(numerics[i].value)) {
|
||||
numerics[i].classList.add("fail_val");
|
||||
scrollTop();
|
||||
console.log("failed on integer test for " + numerics[i].name);
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
10
SD_ROOT/wz_mini/www/index.html
Normal file
10
SD_ROOT/wz_mini/www/index.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head><title>WZ Mini</title></head>
|
||||
<body>
|
||||
<h1>wz_mini web server</h1>
|
||||
<p><a href="cgi-bin/config.cgi">Configuration Editor</a></p>
|
||||
<p><a href="car/car.html">Car Interface</a></p>
|
||||
<p><a href="cgi-bin/jpeg.cgi">Current Screen</a></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -79,6 +79,7 @@ NIGHT_DROP_DISABLE="false"
|
||||
DISABLE_MOTOR="false"
|
||||
ENABLE_FSCK_ON_BOOT="false"
|
||||
ENABLE_CAR_DRIVER="false"
|
||||
ENABLE_LOCAL_DNS="false"
|
||||
|
||||
#####DEBUG#####
|
||||
#drops you to a shell via serial, doesn't load app_init.sh
|
||||
@@ -86,5 +87,8 @@ DEBUG_ENABLED="false"
|
||||
DEBUG_INITRAMFS_ENABLED="false"
|
||||
DEBUG_PASSWORD="false"
|
||||
|
||||
####WEB####
|
||||
WEB_SERVER_ENABLED="false"
|
||||
|
||||
#####SCRIPTING#####
|
||||
CUSTOM_SCRIPT_PATH="/opt/wz_mini/etc/crontab/start_cron.sh"
|
||||
|
||||
Reference in New Issue
Block a user