mirror of
https://github.com/motioneye-project/motioneyeos.git
synced 2025-07-27 21:26:36 +00:00
merged with thingOS
This commit is contained in:
parent
c4a0ea3a8b
commit
766d7132b5
@ -6,4 +6,6 @@ tmpfs /tmp tmpfs mode=1777 0 0
|
|||||||
sysfs /sys sysfs defaults 0 0
|
sysfs /sys sysfs defaults 0 0
|
||||||
/dev/mmcblk0p1 /boot vfat ro,defaults 0 0
|
/dev/mmcblk0p1 /boot vfat ro,defaults 0 0
|
||||||
/dev/mmcblk0p3 /data ext4 defaults,noatime 0 0
|
/dev/mmcblk0p3 /data ext4 defaults,noatime 0 0
|
||||||
|
/data/output /home/ftp/sdcard rbind rbind 0 0
|
||||||
|
/data/media /home/ftp/storage rbind rbind 0 0
|
||||||
|
|
||||||
|
45
board/common/overlay/etc/init.d/S61proftpd
Executable file
45
board/common/overlay/etc/init.d/S61proftpd
Executable file
@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
test -f /etc/proftpd.conf || exit 0
|
||||||
|
|
||||||
|
test -n "$os_version" || source /etc/init.d/base
|
||||||
|
test -n "$os_debug" || source /etc/init.d/conf
|
||||||
|
|
||||||
|
test "$os_networkless" == "true" && exit 0
|
||||||
|
|
||||||
|
start() {
|
||||||
|
msg_begin "Starting proftpd"
|
||||||
|
mkdir -p /var/run/proftpd
|
||||||
|
touch /var/log/wtmp
|
||||||
|
/usr/sbin/proftpd &>/dev/null
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
msg_begin "Stopping proftpd"
|
||||||
|
killall proftpd &>/dev/null
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|restart}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
59
board/common/overlay/etc/init.d/S62smb
Executable file
59
board/common/overlay/etc/init.d/S62smb
Executable file
@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
test -f /etc/samba/smb.conf || exit 0
|
||||||
|
|
||||||
|
test -n "$os_version" || source /etc/init.d/base
|
||||||
|
test -n "$os_debug" || source /etc/init.d/conf
|
||||||
|
|
||||||
|
test "$os_networkless" == "true" && exit 0
|
||||||
|
|
||||||
|
start() {
|
||||||
|
msg_begin "Setting smb admin password"
|
||||||
|
|
||||||
|
mkdir -p /var/log/samba
|
||||||
|
mkdir -p /var/lib/samba/private
|
||||||
|
|
||||||
|
password=$(/etc/init.d/adminpw)
|
||||||
|
echo -e "$password\n$password\n" | /usr/bin/smbpasswd -a admin -s > /dev/null
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
|
||||||
|
msg_begin "Starting smbd"
|
||||||
|
smbd -D
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
|
||||||
|
msg_begin "Starting nmbd"
|
||||||
|
nmbd -D
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
msg_begin "Stopping smbd"
|
||||||
|
killall smbd &>/dev/null
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
|
||||||
|
msg_begin "Stopping nmbd"
|
||||||
|
killall nmbd &>/dev/null
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|restart}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit $?
|
||||||
|
|
149
board/common/overlay/etc/init.d/S85motioneye
Executable file
149
board/common/overlay/etc/init.d/S85motioneye
Executable file
@ -0,0 +1,149 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
sys_conf="/etc/motioneye.conf"
|
||||||
|
boot_conf="/boot/motioneye.conf"
|
||||||
|
conf="/data/etc/motioneye.conf"
|
||||||
|
motion_conf="/data/etc/motion.conf"
|
||||||
|
watch_conf="/data/etc/watch.conf"
|
||||||
|
|
||||||
|
meyewatch_timeout=120
|
||||||
|
meyewatch_disable="false"
|
||||||
|
dev_v4l_by_id="/dev/v4l/by-id/"
|
||||||
|
media_dir="/data/output"
|
||||||
|
|
||||||
|
if ! [ -f $conf ]; then
|
||||||
|
if [ -f $boot_conf ]; then
|
||||||
|
cp $boor_conf $conf
|
||||||
|
elif [ -f $sys_conf ]; then
|
||||||
|
cp $sys_conf $conf
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
test -f "$conf" || exit 0
|
||||||
|
|
||||||
|
test -r $watch_conf && source $watch_conf
|
||||||
|
|
||||||
|
test -n "$os_version" || source /etc/init.d/base
|
||||||
|
|
||||||
|
opts=$(cat "$conf" | while read line; do echo "--$line"; done)
|
||||||
|
port=$(echo "$opts" | grep -oE 'port [[:digit:]]+' | cut -d ' ' -f 2)
|
||||||
|
|
||||||
|
responsive() {
|
||||||
|
wget --method=HEAD -q -t 1 -T 2 -O - http://127.0.0.1:$port &>/dev/null && return 0 || return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
watch() {
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
sleep 5
|
||||||
|
if responsive; then
|
||||||
|
count=0
|
||||||
|
else
|
||||||
|
if [ $count -lt $meyewatch_timeout ]; then
|
||||||
|
count=$(($count + 5))
|
||||||
|
else
|
||||||
|
logger -t motioneye -s "not responding for $meyewatch_timeout seconds, rebooting"
|
||||||
|
reboot
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
find_persistent_device() {
|
||||||
|
device=$1
|
||||||
|
|
||||||
|
if ! [ -d $dev_v4l_by_id ]; then
|
||||||
|
echo $device
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
for p in $dev_v4l_by_id/*; do
|
||||||
|
if [ $(realpath "$p") == $device ]; then
|
||||||
|
echo $p | sed 's#//*#/#g'
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo $device
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
msg_begin "Starting motioneye"
|
||||||
|
|
||||||
|
mkdir -p $media_dir
|
||||||
|
meyectl startserver -b -c $conf -l
|
||||||
|
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
if responsive; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $count -gt $meyewatch_timeout ]; then
|
||||||
|
msg_fail
|
||||||
|
test "$meyewatch_disable" == "false" && reboot
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
count=$(($count + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
# add connected camera(s) with default settings
|
||||||
|
if responsive && ! [ -f $motion_conf ]; then
|
||||||
|
count=$(ls /dev/video* 2>/dev/null | wc -l)
|
||||||
|
index=1
|
||||||
|
for device in $(ls /dev/video* 2>/dev/null); do
|
||||||
|
if [ "$count" -gt "1" ]; then
|
||||||
|
output_dir="/data/output/camera$index/"
|
||||||
|
else
|
||||||
|
output_dir="/data/output/"
|
||||||
|
fi
|
||||||
|
loc="/config/add/?_username=admin"
|
||||||
|
device=$(find_persistent_device $device)
|
||||||
|
body="{\"path\": \"$device\", \"proto\": \"v4l2\"}"
|
||||||
|
signature=$(echo -n "POST:$loc:$body:" | sha1sum | cut -d ' ' -f 1)
|
||||||
|
|
||||||
|
curl -s -m 60 --data "$body" "http://127.0.0.1:$port$loc&_signature=$signature" > /dev/null
|
||||||
|
index=$(($index + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
sync
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$meyewatch_disable" == "false" ]; then
|
||||||
|
watch &
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_done
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
msg_begin "Stopping motioneye"
|
||||||
|
meyectl stopserver -c $conf &>/dev/null
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
ps | grep motioneye | grep -v $$ | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1 | xargs -r kill
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|restart}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit $?
|
||||||
|
|
@ -5,3 +5,7 @@ options rndis_wlan power_save=0
|
|||||||
options b43 hwpctl=0
|
options b43 hwpctl=0
|
||||||
options ath6kl_core suspend_mode=1
|
options ath6kl_core suspend_mode=1
|
||||||
options brcmfmac roamoff=1
|
options brcmfmac roamoff=1
|
||||||
|
|
||||||
|
# media
|
||||||
|
options stk1160 keep_buffers=1
|
||||||
|
|
||||||
|
24
board/common/overlay/etc/motioneye.conf
Normal file
24
board/common/overlay/etc/motioneye.conf
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
conf_path /data/etc
|
||||||
|
run_path /tmp
|
||||||
|
log_path /var/log
|
||||||
|
media_path /data/output
|
||||||
|
motion_binary /usr/bin/motion
|
||||||
|
log_level info
|
||||||
|
listen 0.0.0.0
|
||||||
|
port 80
|
||||||
|
mount_check_interval 300
|
||||||
|
motion_check_interval 10
|
||||||
|
cleanup_interval 43200
|
||||||
|
remote_request_timeout 10
|
||||||
|
mjpg_client_timeout 10
|
||||||
|
mjpg_client_idle_timeout 10
|
||||||
|
smb_shares true
|
||||||
|
smb_mount_root /data/media
|
||||||
|
wpa_supplicant_conf /data/etc/wpa_supplicant.conf
|
||||||
|
local_time_file /data/etc/localtime
|
||||||
|
enable_reboot true
|
||||||
|
enable_update true
|
||||||
|
smtp_timeout 60
|
||||||
|
zip_timeout 500
|
||||||
|
add_remove_cameras true
|
||||||
|
|
@ -7,6 +7,6 @@ os_ppp="ppp0"
|
|||||||
os_networkless="false"
|
os_networkless="false"
|
||||||
os_country="GB"
|
os_country="GB"
|
||||||
os_firmware_method="github"
|
os_firmware_method="github"
|
||||||
os_firmware_repo="ccrisan/thingos"
|
os_firmware_repo="ccrisan/motioneyeos"
|
||||||
os_firmware_username=""
|
os_firmware_username=""
|
||||||
os_firmware_password=""
|
os_firmware_password=""
|
||||||
|
25
board/common/overlay/etc/proftpd.conf
Normal file
25
board/common/overlay/etc/proftpd.conf
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
ServerIdent off
|
||||||
|
ServerType standalone
|
||||||
|
DefaultServer on
|
||||||
|
Port 21
|
||||||
|
UseIPv6 off
|
||||||
|
Umask 022
|
||||||
|
MaxInstances 4
|
||||||
|
User ftp
|
||||||
|
Group nogroup
|
||||||
|
DefaultRoot /home/ftp
|
||||||
|
AllowOverwrite on
|
||||||
|
RequireValidShell off
|
||||||
|
UseFtpUsers off
|
||||||
|
RootLogin on
|
||||||
|
|
||||||
|
<Limit SITE_CHMOD>
|
||||||
|
DenyAll
|
||||||
|
</Limit>
|
||||||
|
|
||||||
|
<Limit WRITE>
|
||||||
|
DenyAll
|
||||||
|
</Limit>
|
||||||
|
|
||||||
|
Include /data/etc/proftpd*.conf
|
||||||
|
|
31
board/common/overlay/etc/samba/smb.conf
Normal file
31
board/common/overlay/etc/samba/smb.conf
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
[global]
|
||||||
|
workgroup = MOTIONEYE
|
||||||
|
server string = motionEye
|
||||||
|
security = user
|
||||||
|
map to guest = bad user
|
||||||
|
encrypt passwords = yes
|
||||||
|
private dir = /var/lib/samba/private
|
||||||
|
public = no
|
||||||
|
writable = no
|
||||||
|
include = /data/etc/smb.conf
|
||||||
|
load printers = no
|
||||||
|
printing = bsd
|
||||||
|
printcap name = /dev/null
|
||||||
|
disable spoolss = yes
|
||||||
|
bind interfaces only = yes
|
||||||
|
interfaces = eth0 wlan0
|
||||||
|
log level = 0
|
||||||
|
syslog = 0
|
||||||
|
preferred master = no
|
||||||
|
domain master = no
|
||||||
|
local master = no
|
||||||
|
os level = 0
|
||||||
|
|
||||||
|
[sdcard]
|
||||||
|
comment = SD Card Output Directory
|
||||||
|
path = /data/output
|
||||||
|
|
||||||
|
[storage]
|
||||||
|
comment = Attached Storage Devices
|
||||||
|
path = /data/media
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
os_name="motionEyeOS"
|
os_name="motionEyeOS"
|
||||||
os_short_name="motioneyeos"
|
os_short_name="motioneyeos"
|
||||||
os_prefix="meye"
|
os_prefix="meye"
|
||||||
os_version="20170212"
|
os_version="20170219"
|
||||||
|
0
board/common/skeleton/home/ftp/.empty
Normal file
0
board/common/skeleton/home/ftp/.empty
Normal file
0
board/common/skeleton/home/ftp/sdcard/.empty
Normal file
0
board/common/skeleton/home/ftp/sdcard/.empty
Normal file
0
board/common/skeleton/home/ftp/storage/.empty
Normal file
0
board/common/skeleton/home/ftp/storage/.empty
Normal file
@ -6,6 +6,6 @@ os_wlan="wlan0"
|
|||||||
os_ppp="ppp0"
|
os_ppp="ppp0"
|
||||||
os_networkless="false"
|
os_networkless="false"
|
||||||
os_firmware_method="github"
|
os_firmware_method="github"
|
||||||
os_firmware_repo="ccrisan/thingos"
|
os_firmware_repo="ccrisan/motioneyeos"
|
||||||
os_firmware_username=""
|
os_firmware_username=""
|
||||||
os_firmware_password=""
|
os_firmware_password=""
|
||||||
|
@ -6,6 +6,6 @@ os_wlan="wlan0"
|
|||||||
os_ppp="ppp0"
|
os_ppp="ppp0"
|
||||||
os_networkless="false"
|
os_networkless="false"
|
||||||
os_firmware_method="github"
|
os_firmware_method="github"
|
||||||
os_firmware_repo="ccrisan/thingos"
|
os_firmware_repo="ccrisan/motioneyeos"
|
||||||
os_firmware_username=""
|
os_firmware_username=""
|
||||||
os_firmware_password=""
|
os_firmware_password=""
|
||||||
|
310
board/raspberrypi/motioneye-modules/boardctl.py
Normal file
310
board/raspberrypi/motioneye-modules/boardctl.py
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
|
||||||
|
# Copyright (c) 2015 Calin Crisan
|
||||||
|
# This file is part of motionEyeOS.
|
||||||
|
#
|
||||||
|
# motionEyeOS 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os.path
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from config import additional_config
|
||||||
|
|
||||||
|
import streameyectl
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_TXT = '/boot/config.txt'
|
||||||
|
MONITOR = '/data/etc/monitor_1'
|
||||||
|
|
||||||
|
MONITOR_SCRIPT = '''#!/bin/bash
|
||||||
|
|
||||||
|
net_tmp=/tmp/netspeed.tmp
|
||||||
|
temp=$(($(cat /sys/devices/virtual/thermal/thermal_zone0/temp) / 1000))
|
||||||
|
load=$(cat /proc/loadavg | cut -d ' ' -f 2)
|
||||||
|
recv=$(cat /proc/net/dev | grep -v 'lo:' | tr -s ' ' | cut -d ' ' -f 3 | tail -n +3 | awk '{s+=$1} END {print s}')
|
||||||
|
send=$(cat /proc/net/dev | grep -v 'lo:' | tr -s ' ' | cut -d ' ' -f 11 | tail -n +3 | awk '{s+=$1} END {print s}')
|
||||||
|
total=$(($recv + $send))
|
||||||
|
|
||||||
|
if [ -e $net_tmp ]; then
|
||||||
|
prev_total=$(cat $net_tmp)
|
||||||
|
speed=$(($total - $prev_total))
|
||||||
|
else
|
||||||
|
speed=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $total > $net_tmp
|
||||||
|
speed=$(($speed / 1024))
|
||||||
|
|
||||||
|
echo -n "$temp°|$load|${speed}kB/s"
|
||||||
|
'''
|
||||||
|
|
||||||
|
OVERCLOCK = {
|
||||||
|
700: '700|250|400|0',
|
||||||
|
800: '800|250|400|0',
|
||||||
|
900: '900|250|450|0',
|
||||||
|
950: '950|250|450|0',
|
||||||
|
1000: '1000|500|600|6',
|
||||||
|
1001: '1001|300|450|6'
|
||||||
|
}
|
||||||
|
|
||||||
|
def _is_pi_zero():
|
||||||
|
try:
|
||||||
|
subprocess.check_call('grep -q "^Revision\s*:\s*[ 123][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]09[0-9a-fA-F]$" /proc/cpuinfo', shell=True)
|
||||||
|
return True
|
||||||
|
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _get_board_settings():
|
||||||
|
gpu_mem = 128
|
||||||
|
camera_led = True
|
||||||
|
if _is_pi_zero():
|
||||||
|
arm_freq = 1001
|
||||||
|
|
||||||
|
else:
|
||||||
|
arm_freq = 700
|
||||||
|
|
||||||
|
if os.path.exists(CONFIG_TXT):
|
||||||
|
logging.debug('reading board settings from %s' % CONFIG_TXT)
|
||||||
|
|
||||||
|
with open(CONFIG_TXT) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith('#'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
parts = line.split('=', 1)
|
||||||
|
if len(parts) != 2:
|
||||||
|
continue
|
||||||
|
|
||||||
|
name, value = parts
|
||||||
|
name = name.strip()
|
||||||
|
value = value.strip()
|
||||||
|
|
||||||
|
if name.startswith('gpu_mem'):
|
||||||
|
gpu_mem = int(value)
|
||||||
|
|
||||||
|
elif name == 'arm_freq':
|
||||||
|
arm_freq = int(value)
|
||||||
|
|
||||||
|
elif name == 'disable_camera_led':
|
||||||
|
camera_led = value == '0'
|
||||||
|
|
||||||
|
overclock = OVERCLOCK.get(arm_freq, '700|250|400|0')
|
||||||
|
|
||||||
|
s = {
|
||||||
|
'gpuMem': gpu_mem,
|
||||||
|
'overclock': overclock,
|
||||||
|
'cameraLed': camera_led
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.debug('board settings: gpu_mem=%(gpuMem)s, overclock=%(overclock)s, camera_led=%(cameraLed)s' % s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def _set_board_settings(s):
|
||||||
|
s.setdefault('gpuMem', 128)
|
||||||
|
s.setdefault('overclock', '700|250|400|0')
|
||||||
|
s.setdefault('cameraLed', True)
|
||||||
|
|
||||||
|
old_settings = _get_board_settings()
|
||||||
|
if s == old_settings:
|
||||||
|
return # nothing has changed
|
||||||
|
|
||||||
|
seen = set()
|
||||||
|
|
||||||
|
logging.debug('writing board settings to %s: ' % CONFIG_TXT +
|
||||||
|
'gpu_mem=%(gpuMem)s, overclock=%(overclock)s, camera_led=%(cameraLed)s' % s)
|
||||||
|
|
||||||
|
arm_freq, gpu_freq, sdram_freq, over_voltage = s['overclock'].split('|')
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
if os.path.exists(CONFIG_TXT):
|
||||||
|
with open(CONFIG_TXT) as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
line = line.strip('#')
|
||||||
|
|
||||||
|
try:
|
||||||
|
name, _ = line.split('=', 1)
|
||||||
|
name = name.strip()
|
||||||
|
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
seen.add(name)
|
||||||
|
|
||||||
|
if name.startswith('gpu_mem'):
|
||||||
|
lines[i] = '%s=%s' % (name, s['gpuMem'])
|
||||||
|
|
||||||
|
elif name == 'arm_freq':
|
||||||
|
lines[i] = 'arm_freq=%s' % arm_freq
|
||||||
|
|
||||||
|
elif name in ['gpu_freq', 'core_freq']:
|
||||||
|
lines[i] = '%s=%s' % (name, gpu_freq)
|
||||||
|
|
||||||
|
elif name == 'sdram_freq':
|
||||||
|
lines[i] = 'sdram_freq=%s' % sdram_freq
|
||||||
|
|
||||||
|
elif name == 'over_voltage':
|
||||||
|
lines[i] = 'over_voltage=%s' % over_voltage
|
||||||
|
|
||||||
|
elif name == 'disable_camera_led':
|
||||||
|
lines[i] = 'disable_camera_led=%s' % ['1', '0'][s['cameraLed']]
|
||||||
|
|
||||||
|
if 'gpu_mem' not in seen:
|
||||||
|
lines.append('gpu_mem=%s' % s['gpuMem'])
|
||||||
|
|
||||||
|
if 'gpu_mem_256' not in seen:
|
||||||
|
lines.append('gpu_mem_256=%s' % s['gpuMem'])
|
||||||
|
|
||||||
|
if 'gpu_mem_512' not in seen:
|
||||||
|
lines.append('gpu_mem_512=%s' % s['gpuMem'])
|
||||||
|
|
||||||
|
if 'arm_freq' not in seen:
|
||||||
|
lines.append('arm_freq=%s' % arm_freq)
|
||||||
|
|
||||||
|
if 'gpu_freq' not in seen:
|
||||||
|
lines.append('gpu_freq=%s' % gpu_freq)
|
||||||
|
|
||||||
|
if 'sdram_freq' not in seen:
|
||||||
|
lines.append('sdram_freq=%s' % sdram_freq)
|
||||||
|
|
||||||
|
if 'over_voltage' not in seen:
|
||||||
|
lines.append('over_voltage=%s' % over_voltage)
|
||||||
|
|
||||||
|
if 'disable_camera_led' not in seen:
|
||||||
|
lines.append('disable_camera_led=%s' % ['1', '0'][s['cameraLed']])
|
||||||
|
|
||||||
|
logging.debug('remounting /boot read-write')
|
||||||
|
if os.system('mount -o remount,rw /boot'):
|
||||||
|
logging.error('failed to remount /boot read-write')
|
||||||
|
|
||||||
|
with open(CONFIG_TXT, 'w') as f:
|
||||||
|
for line in lines:
|
||||||
|
if not line.strip():
|
||||||
|
continue
|
||||||
|
if not line.endswith('\n'):
|
||||||
|
line += '\n'
|
||||||
|
f.write(line)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_sys_mon():
|
||||||
|
return os.access(MONITOR, os.X_OK)
|
||||||
|
|
||||||
|
|
||||||
|
def _set_sys_mon(sys_mon):
|
||||||
|
if sys_mon:
|
||||||
|
if os.access(MONITOR, os.X_OK):
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
if os.path.exists(MONITOR):
|
||||||
|
os.system('chmod +x %s' % MONITOR)
|
||||||
|
|
||||||
|
else:
|
||||||
|
with open(MONITOR, 'w') as f:
|
||||||
|
f.write(MONITOR_SCRIPT)
|
||||||
|
|
||||||
|
os.system('chmod +x %s' % MONITOR)
|
||||||
|
|
||||||
|
else:
|
||||||
|
if os.access(MONITOR, os.X_OK):
|
||||||
|
os.system('chmod -x %s' % MONITOR)
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def boardSeparator():
|
||||||
|
return {
|
||||||
|
'type': 'separator',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def gpuMem():
|
||||||
|
return {
|
||||||
|
'label': 'GPU Memory',
|
||||||
|
'description': 'set the amount of memory reserved for the GPU (choose at least 96MB if you use the CSI camera board)',
|
||||||
|
'type': 'number',
|
||||||
|
'min': '16',
|
||||||
|
'max': '448',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_board_settings,
|
||||||
|
'set': _set_board_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def cameraLed():
|
||||||
|
return {
|
||||||
|
'label': 'Enable CSI Camera Led',
|
||||||
|
'description': 'control the led on the CSI camera board',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_board_settings,
|
||||||
|
'set': _set_board_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def overclock():
|
||||||
|
return {
|
||||||
|
'label': 'Overclocking',
|
||||||
|
'description': 'choose an overclocking preset for your Raspberry PI',
|
||||||
|
'type': 'choices',
|
||||||
|
'choices': [
|
||||||
|
('700|250|400|0', 'none (700/250/400/0)'),
|
||||||
|
('800|250|400|0', 'modest (800/250/400/0)'),
|
||||||
|
('900|250|450|0', 'medium (900/250/450/0)'),
|
||||||
|
('950|250|450|0', 'high (950/250/450/0)'),
|
||||||
|
('1000|500|600|6', 'turbo (1000/500/600/6)'),
|
||||||
|
('1001|300|450|6', 'PiZero (1000/300/450/6)'),
|
||||||
|
],
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_board_settings,
|
||||||
|
'set': _set_board_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def sysMon():
|
||||||
|
return {
|
||||||
|
'label': 'Enable System Monitoring',
|
||||||
|
'description': 'when this is enabled, system monitoring info will be overlaid on top of the first camera frame',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': False,
|
||||||
|
'get': _get_sys_mon,
|
||||||
|
'set': _set_sys_mon
|
||||||
|
}
|
||||||
|
|
1172
board/raspberrypi/motioneye-modules/streameyectl.py
Normal file
1172
board/raspberrypi/motioneye-modules/streameyectl.py
Normal file
File diff suppressed because it is too large
Load Diff
51
board/raspberrypi/overlay/etc/init.d/S84streameye
Executable file
51
board/raspberrypi/overlay/etc/init.d/S84streameye
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
motioneye_conf_dir="/data/etc/"
|
||||||
|
|
||||||
|
test -n "$os_version" || source /etc/init.d/base
|
||||||
|
|
||||||
|
enabled() {
|
||||||
|
test $(ls -1 $motioneye_conf_dir/thread-*.conf 2>/dev/null| wc -l) == 1 || return 1
|
||||||
|
|
||||||
|
grep '# @proto mjpeg' $motioneye_conf_dir/thread-1.conf &>/dev/null || return 1
|
||||||
|
|
||||||
|
grep -E '# @url http://(.*)127.0.0.1:' $motioneye_conf_dir/thread-1.conf &>/dev/null || return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled || exit 0
|
||||||
|
|
||||||
|
start() {
|
||||||
|
msg_begin "Starting streameye"
|
||||||
|
streameye.sh start
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
msg_begin "Stopping streameye"
|
||||||
|
streameye.sh stop
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|restart}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit $?
|
||||||
|
|
3
board/raspberrypi/overlay/etc/modules
Normal file
3
board/raspberrypi/overlay/etc/modules
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
bcm2835-v4l2 max_video_width=2592 max_video_height=1944
|
||||||
|
bcm2835-wdt
|
||||||
|
|
93
board/raspberrypi/overlay/usr/bin/streameye.sh
Executable file
93
board/raspberrypi/overlay/usr/bin/streameye.sh
Executable file
@ -0,0 +1,93 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
RASPIMJPEG_CONF=/data/etc/raspimjpeg.conf
|
||||||
|
RASPIMJPEG_LOG=/var/log/raspimjpeg.log
|
||||||
|
MOTIONEYE_CONF=/data/etc/motioneye.conf
|
||||||
|
STREAMEYE_CONF=/data/etc/streameye.conf
|
||||||
|
STREAMEYE_LOG=/var/log/streameye.log
|
||||||
|
|
||||||
|
test -r $RASPIMJPEG_CONF || exit 1
|
||||||
|
test -r $STREAMEYE_CONF || exit 1
|
||||||
|
|
||||||
|
watch() {
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
sleep 5
|
||||||
|
if ! ps aux | grep raspimjpeg.py | grep -v grep &>/dev/null; then
|
||||||
|
logger -t streameye -s "not running, respawning"
|
||||||
|
start
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
|
if [ -n "$pid" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
raspimjpeg_opts=""
|
||||||
|
while read line; do
|
||||||
|
if echo "$line" | grep false &>/dev/null; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if echo "$line" | grep true &>/dev/null; then
|
||||||
|
line=$(echo $line | cut -d ' ' -f 1)
|
||||||
|
fi
|
||||||
|
raspimjpeg_opts="$raspimjpeg_opts --$line"
|
||||||
|
done < $RASPIMJPEG_CONF
|
||||||
|
|
||||||
|
source $STREAMEYE_CONF
|
||||||
|
streameye_opts="-p $PORT"
|
||||||
|
if [ -n "$CREDENTIALS" ] && [ "$AUTH" = "basic" ]; then
|
||||||
|
streameye_opts="$streameye_opts -a basic -c $CREDENTIALS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -r $MOTIONEYE_CONF ] && grep 'log-level debug' $MOTIONEYE_CONF >/dev/null; then
|
||||||
|
raspimjpeg_opts="$raspimjpeg_opts -d"
|
||||||
|
streameye_opts="$streameye_opts -d"
|
||||||
|
fi
|
||||||
|
|
||||||
|
raspimjpeg.py $raspimjpeg_opts 2>$RASPIMJPEG_LOG | streameye $streameye_opts &>$STREAMEYE_LOG &
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop() {
|
||||||
|
# stop the streameye background watch process
|
||||||
|
ps | grep streameye.sh | grep -v $$ | grep -v S94streameye| grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1 | xargs -r kill
|
||||||
|
|
||||||
|
# stop the raspimjpeg process
|
||||||
|
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
|
if [ -z "$pid" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
kill -HUP "$pid" &>/dev/null
|
||||||
|
count=0
|
||||||
|
while kill -0 "$pid" &>/dev/null && [ $count -lt 5 ]; do
|
||||||
|
sleep 1
|
||||||
|
count=$(($count + 1))
|
||||||
|
done
|
||||||
|
kill -KILL "$pid" &>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
watch &
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
watch &
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo $"Usage: $0 {start|stop|restart}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
290
board/raspberrypi2/motioneye-modules/boardctl.py
Normal file
290
board/raspberrypi2/motioneye-modules/boardctl.py
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
|
||||||
|
# Copyright (c) 2015 Calin Crisan
|
||||||
|
# This file is part of motionEyeOS.
|
||||||
|
#
|
||||||
|
# motionEyeOS 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
from config import additional_config
|
||||||
|
|
||||||
|
import streameyectl
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_TXT = '/boot/config.txt'
|
||||||
|
MONITOR = '/data/etc/monitor_1'
|
||||||
|
|
||||||
|
MONITOR_SCRIPT = '''#!/bin/bash
|
||||||
|
|
||||||
|
net_tmp=/tmp/netspeed.tmp
|
||||||
|
temp=$(($(cat /sys/devices/virtual/thermal/thermal_zone0/temp) / 1000))
|
||||||
|
load=$(cat /proc/loadavg | cut -d ' ' -f 2)
|
||||||
|
recv=$(cat /proc/net/dev | grep -v 'lo:' | tr -s ' ' | cut -d ' ' -f 3 | tail -n +3 | awk '{s+=$1} END {print s}')
|
||||||
|
send=$(cat /proc/net/dev | grep -v 'lo:' | tr -s ' ' | cut -d ' ' -f 11 | tail -n +3 | awk '{s+=$1} END {print s}')
|
||||||
|
total=$(($recv + $send))
|
||||||
|
|
||||||
|
if [ -e $net_tmp ]; then
|
||||||
|
prev_total=$(cat $net_tmp)
|
||||||
|
speed=$(($total - $prev_total))
|
||||||
|
else
|
||||||
|
speed=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $total > $net_tmp
|
||||||
|
speed=$(($speed / 1024))
|
||||||
|
|
||||||
|
echo -n "$temp°|$load|${speed}kB/s"
|
||||||
|
'''
|
||||||
|
|
||||||
|
OVERCLOCK = {
|
||||||
|
700: '700|250|400|0',
|
||||||
|
800: '800|250|400|0',
|
||||||
|
900: '900|250|450|0',
|
||||||
|
950: '950|250|450|0',
|
||||||
|
1000: '1000|500|600|6',
|
||||||
|
1001: '1001|500|500|2'
|
||||||
|
}
|
||||||
|
|
||||||
|
def _get_board_settings():
|
||||||
|
gpu_mem = 128
|
||||||
|
camera_led = True
|
||||||
|
arm_freq = 1001
|
||||||
|
|
||||||
|
if os.path.exists(CONFIG_TXT):
|
||||||
|
logging.debug('reading board settings from %s' % CONFIG_TXT)
|
||||||
|
|
||||||
|
with open(CONFIG_TXT) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith('#'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
parts = line.split('=', 1)
|
||||||
|
if len(parts) != 2:
|
||||||
|
continue
|
||||||
|
|
||||||
|
name, value = parts
|
||||||
|
name = name.strip()
|
||||||
|
value = value.strip()
|
||||||
|
|
||||||
|
if name == 'gpu_mem':
|
||||||
|
gpu_mem = int(value)
|
||||||
|
|
||||||
|
elif name == 'arm_freq':
|
||||||
|
arm_freq = int(value)
|
||||||
|
|
||||||
|
elif name == 'disable_camera_led':
|
||||||
|
camera_led = value == '0'
|
||||||
|
|
||||||
|
overclock = OVERCLOCK.get(arm_freq, '700|250|400|0')
|
||||||
|
|
||||||
|
s = {
|
||||||
|
'gpuMem': gpu_mem,
|
||||||
|
'overclock': overclock,
|
||||||
|
'cameraLed': camera_led
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.debug('board settings: gpu_mem=%(gpuMem)s, overclock=%(overclock)s, camera_led=%(cameraLed)s' % s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def _set_board_settings(s):
|
||||||
|
s.setdefault('gpuMem', 128)
|
||||||
|
s.setdefault('overclock', '700|250|400|0')
|
||||||
|
s.setdefault('cameraLed', True)
|
||||||
|
|
||||||
|
old_settings = _get_board_settings()
|
||||||
|
if s == old_settings:
|
||||||
|
return # nothing has changed
|
||||||
|
|
||||||
|
seen = set()
|
||||||
|
|
||||||
|
logging.debug('writing board settings to %s: ' % CONFIG_TXT +
|
||||||
|
'gpu_mem=%(gpuMem)s, overclock=%(overclock)s, camera_led=%(cameraLed)s' % s)
|
||||||
|
|
||||||
|
arm_freq, gpu_freq, sdram_freq, over_voltage = s['overclock'].split('|')
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
if os.path.exists(CONFIG_TXT):
|
||||||
|
with open(CONFIG_TXT) as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
line = line.strip('#')
|
||||||
|
|
||||||
|
try:
|
||||||
|
name, _ = line.split('=', 1)
|
||||||
|
name = name.strip()
|
||||||
|
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
seen.add(name)
|
||||||
|
|
||||||
|
if name == 'gpu_mem':
|
||||||
|
lines[i] = '%s=%s' % (name, s['gpuMem'])
|
||||||
|
|
||||||
|
elif name == 'arm_freq':
|
||||||
|
lines[i] = 'arm_freq=%s' % arm_freq
|
||||||
|
|
||||||
|
elif name in ['gpu_freq', 'core_freq']:
|
||||||
|
lines[i] = '%s=%s' % (name, gpu_freq)
|
||||||
|
|
||||||
|
elif name == 'sdram_freq':
|
||||||
|
lines[i] = 'sdram_freq=%s' % sdram_freq
|
||||||
|
|
||||||
|
elif name == 'over_voltage':
|
||||||
|
lines[i] = 'over_voltage=%s' % over_voltage
|
||||||
|
|
||||||
|
elif name == 'disable_camera_led':
|
||||||
|
lines[i] = 'disable_camera_led=%s' % ['1', '0'][s['cameraLed']]
|
||||||
|
|
||||||
|
if 'gpu_mem' not in seen:
|
||||||
|
lines.append('gpu_mem=%s' % s['gpuMem'])
|
||||||
|
|
||||||
|
if 'arm_freq' not in seen:
|
||||||
|
lines.append('arm_freq=%s' % arm_freq)
|
||||||
|
|
||||||
|
if 'gpu_freq' not in seen:
|
||||||
|
lines.append('gpu_freq=%s' % gpu_freq)
|
||||||
|
|
||||||
|
if 'sdram_freq' not in seen:
|
||||||
|
lines.append('sdram_freq=%s' % sdram_freq)
|
||||||
|
|
||||||
|
if 'over_voltage' not in seen:
|
||||||
|
lines.append('over_voltage=%s' % over_voltage)
|
||||||
|
|
||||||
|
if 'disable_camera_led' not in seen:
|
||||||
|
lines.append('disable_camera_led=%s' % ['1', '0'][s['cameraLed']])
|
||||||
|
|
||||||
|
logging.debug('remounting /boot read-write')
|
||||||
|
if os.system('mount -o remount,rw /boot'):
|
||||||
|
logging.error('failed to remount /boot read-write')
|
||||||
|
|
||||||
|
with open(CONFIG_TXT, 'w') as f:
|
||||||
|
for line in lines:
|
||||||
|
if not line.strip():
|
||||||
|
continue
|
||||||
|
if not line.endswith('\n'):
|
||||||
|
line += '\n'
|
||||||
|
f.write(line)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_sys_mon():
|
||||||
|
return os.access(MONITOR, os.X_OK)
|
||||||
|
|
||||||
|
|
||||||
|
def _set_sys_mon(sys_mon):
|
||||||
|
if sys_mon:
|
||||||
|
if os.access(MONITOR, os.X_OK):
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
if os.path.exists(MONITOR):
|
||||||
|
os.system('chmod +x %s' % MONITOR)
|
||||||
|
|
||||||
|
else:
|
||||||
|
with open(MONITOR, 'w') as f:
|
||||||
|
f.write(MONITOR_SCRIPT)
|
||||||
|
|
||||||
|
os.system('chmod +x %s' % MONITOR)
|
||||||
|
|
||||||
|
else:
|
||||||
|
if os.access(MONITOR, os.X_OK):
|
||||||
|
os.system('chmod -x %s' % MONITOR)
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def boardSeparator():
|
||||||
|
return {
|
||||||
|
'type': 'separator',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def gpuMem():
|
||||||
|
return {
|
||||||
|
'label': 'GPU Memory',
|
||||||
|
'description': 'set the amount of memory reserved for the GPU (choose at least 96MB if you use the CSI camera board)',
|
||||||
|
'type': 'number',
|
||||||
|
'min': '16',
|
||||||
|
'max': '944',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_board_settings,
|
||||||
|
'set': _set_board_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def cameraLed():
|
||||||
|
return {
|
||||||
|
'label': 'Enable CSI Camera Led',
|
||||||
|
'description': 'control the led on the CSI camera board',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_board_settings,
|
||||||
|
'set': _set_board_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def overclock():
|
||||||
|
return {
|
||||||
|
'label': 'Overclocking',
|
||||||
|
'description': 'choose an overclocking preset for your Raspberry PI',
|
||||||
|
'type': 'choices',
|
||||||
|
'choices': [
|
||||||
|
('700|250|400|0', 'none (700/250/400/0)'),
|
||||||
|
('800|250|400|0', 'modest (800/250/400/0)'),
|
||||||
|
('900|250|450|0', 'medium (900/250/450/0)'),
|
||||||
|
('950|250|450|0', 'high (950/250/450/0)'),
|
||||||
|
('1000|500|600|6', 'turbo (1000/500/600/6)'),
|
||||||
|
('1001|500|500|2', 'Pi2 (1000/500/500/2)')
|
||||||
|
],
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_board_settings,
|
||||||
|
'set': _set_board_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def sysMon():
|
||||||
|
return {
|
||||||
|
'label': 'Enable System Monitoring',
|
||||||
|
'description': 'when this is enabled, system monitoring info will be overlaid on top of the first camera frame',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': False,
|
||||||
|
'get': _get_sys_mon,
|
||||||
|
'set': _set_sys_mon
|
||||||
|
}
|
||||||
|
|
1172
board/raspberrypi2/motioneye-modules/streameyectl.py
Normal file
1172
board/raspberrypi2/motioneye-modules/streameyectl.py
Normal file
File diff suppressed because it is too large
Load Diff
51
board/raspberrypi2/overlay/etc/init.d/S84streameye
Executable file
51
board/raspberrypi2/overlay/etc/init.d/S84streameye
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
motioneye_conf_dir="/data/etc/"
|
||||||
|
|
||||||
|
test -n "$os_version" || source /etc/init.d/base
|
||||||
|
|
||||||
|
enabled() {
|
||||||
|
test $(ls -1 $motioneye_conf_dir/thread-*.conf 2>/dev/null| wc -l) == 1 || return 1
|
||||||
|
|
||||||
|
grep '# @proto mjpeg' $motioneye_conf_dir/thread-1.conf &>/dev/null || return 1
|
||||||
|
|
||||||
|
grep -E '# @url http://(.*)127.0.0.1:' $motioneye_conf_dir/thread-1.conf &>/dev/null || return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled || exit 0
|
||||||
|
|
||||||
|
start() {
|
||||||
|
msg_begin "Starting streameye"
|
||||||
|
streameye.sh start
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
msg_begin "Stopping streameye"
|
||||||
|
streameye.sh stop
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|restart}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit $?
|
||||||
|
|
3
board/raspberrypi2/overlay/etc/modules
Normal file
3
board/raspberrypi2/overlay/etc/modules
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
bcm2835-v4l2 max_video_width=2592 max_video_height=1944
|
||||||
|
bcm2835-wdt
|
||||||
|
|
93
board/raspberrypi2/overlay/usr/bin/streameye.sh
Executable file
93
board/raspberrypi2/overlay/usr/bin/streameye.sh
Executable file
@ -0,0 +1,93 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
RASPIMJPEG_CONF=/data/etc/raspimjpeg.conf
|
||||||
|
RASPIMJPEG_LOG=/var/log/raspimjpeg.log
|
||||||
|
MOTIONEYE_CONF=/data/etc/motioneye.conf
|
||||||
|
STREAMEYE_CONF=/data/etc/streameye.conf
|
||||||
|
STREAMEYE_LOG=/var/log/streameye.log
|
||||||
|
|
||||||
|
test -r $RASPIMJPEG_CONF || exit 1
|
||||||
|
test -r $STREAMEYE_CONF || exit 1
|
||||||
|
|
||||||
|
watch() {
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
sleep 5
|
||||||
|
if ! ps aux | grep raspimjpeg.py | grep -v grep &>/dev/null; then
|
||||||
|
logger -t streameye -s "not running, respawning"
|
||||||
|
start
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
|
if [ -n "$pid" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
raspimjpeg_opts=""
|
||||||
|
while read line; do
|
||||||
|
if echo "$line" | grep false &>/dev/null; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if echo "$line" | grep true &>/dev/null; then
|
||||||
|
line=$(echo $line | cut -d ' ' -f 1)
|
||||||
|
fi
|
||||||
|
raspimjpeg_opts="$raspimjpeg_opts --$line"
|
||||||
|
done < $RASPIMJPEG_CONF
|
||||||
|
|
||||||
|
source $STREAMEYE_CONF
|
||||||
|
streameye_opts="-p $PORT"
|
||||||
|
if [ -n "$CREDENTIALS" ] && [ "$AUTH" = "basic" ]; then
|
||||||
|
streameye_opts="$streameye_opts -a basic -c $CREDENTIALS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -r $MOTIONEYE_CONF ] && grep 'log-level debug' $MOTIONEYE_CONF >/dev/null; then
|
||||||
|
raspimjpeg_opts="$raspimjpeg_opts -d"
|
||||||
|
streameye_opts="$streameye_opts -d"
|
||||||
|
fi
|
||||||
|
|
||||||
|
raspimjpeg.py $raspimjpeg_opts 2>$RASPIMJPEG_LOG | streameye $streameye_opts &>$STREAMEYE_LOG &
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop() {
|
||||||
|
# stop the streameye background watch process
|
||||||
|
ps | grep streameye.sh | grep -v $$ | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1 | xargs -r kill
|
||||||
|
|
||||||
|
# stop the raspimjpeg process
|
||||||
|
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
|
if [ -z "$pid" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
kill -HUP "$pid" &>/dev/null
|
||||||
|
count=0
|
||||||
|
while kill -0 "$pid" &>/dev/null && [ $count -lt 5 ]; do
|
||||||
|
sleep 1
|
||||||
|
count=$(($count + 1))
|
||||||
|
done
|
||||||
|
kill -KILL "$pid" &>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
watch &
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
watch &
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo $"Usage: $0 {start|stop|restart}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
238
board/raspberrypi3/motioneye-modules/boardctl.py
Normal file
238
board/raspberrypi3/motioneye-modules/boardctl.py
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
|
||||||
|
# Copyright (c) 2015 Calin Crisan
|
||||||
|
# This file is part of motionEyeOS.
|
||||||
|
#
|
||||||
|
# motionEyeOS 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
from config import additional_config
|
||||||
|
|
||||||
|
import streameyectl
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_TXT = '/boot/config.txt'
|
||||||
|
MONITOR = '/data/etc/monitor_1'
|
||||||
|
|
||||||
|
MONITOR_SCRIPT = '''#!/bin/bash
|
||||||
|
|
||||||
|
net_tmp=/tmp/netspeed.tmp
|
||||||
|
temp=$(($(cat /sys/devices/virtual/thermal/thermal_zone0/temp) / 1000))
|
||||||
|
load=$(cat /proc/loadavg | cut -d ' ' -f 2)
|
||||||
|
recv=$(cat /proc/net/dev | grep -v 'lo:' | tr -s ' ' | cut -d ' ' -f 3 | tail -n +3 | awk '{s+=$1} END {print s}')
|
||||||
|
send=$(cat /proc/net/dev | grep -v 'lo:' | tr -s ' ' | cut -d ' ' -f 11 | tail -n +3 | awk '{s+=$1} END {print s}')
|
||||||
|
total=$(($recv + $send))
|
||||||
|
|
||||||
|
if [ -e $net_tmp ]; then
|
||||||
|
prev_total=$(cat $net_tmp)
|
||||||
|
speed=$(($total - $prev_total))
|
||||||
|
else
|
||||||
|
speed=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $total > $net_tmp
|
||||||
|
speed=$(($speed / 1024))
|
||||||
|
|
||||||
|
echo -n "$temp°|$load|${speed}kB/s"
|
||||||
|
'''
|
||||||
|
|
||||||
|
OVERCLOCK = {
|
||||||
|
700: '700|250|400|0',
|
||||||
|
800: '800|250|400|0',
|
||||||
|
900: '900|250|450|0',
|
||||||
|
950: '950|250|450|0',
|
||||||
|
1000: '1000|500|600|6',
|
||||||
|
1001: '1001|500|500|2'
|
||||||
|
}
|
||||||
|
|
||||||
|
def _get_board_settings():
|
||||||
|
gpu_mem = 128
|
||||||
|
camera_led = True
|
||||||
|
arm_freq = 700
|
||||||
|
|
||||||
|
if os.path.exists(CONFIG_TXT):
|
||||||
|
logging.debug('reading board settings from %s' % CONFIG_TXT)
|
||||||
|
|
||||||
|
with open(CONFIG_TXT) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith('#'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
parts = line.split('=', 1)
|
||||||
|
if len(parts) != 2:
|
||||||
|
continue
|
||||||
|
|
||||||
|
name, value = parts
|
||||||
|
name = name.strip()
|
||||||
|
value = value.strip()
|
||||||
|
|
||||||
|
if name == 'gpu_mem':
|
||||||
|
gpu_mem = int(value)
|
||||||
|
|
||||||
|
elif name == 'arm_freq':
|
||||||
|
arm_freq = int(value)
|
||||||
|
|
||||||
|
elif name == 'disable_camera_led':
|
||||||
|
camera_led = value == '0'
|
||||||
|
|
||||||
|
|
||||||
|
s = {
|
||||||
|
'gpuMem': gpu_mem,
|
||||||
|
'cameraLed': camera_led
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.debug('board settings: gpu_mem=%(gpuMem)s, camera_led=%(cameraLed)s' % s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def _set_board_settings(s):
|
||||||
|
s.setdefault('gpuMem', 128)
|
||||||
|
s.setdefault('cameraLed', True)
|
||||||
|
|
||||||
|
old_settings = _get_board_settings()
|
||||||
|
if s == old_settings:
|
||||||
|
return # nothing has changed
|
||||||
|
|
||||||
|
seen = set()
|
||||||
|
|
||||||
|
logging.debug('writing board settings to %s: ' % CONFIG_TXT +
|
||||||
|
'gpu_mem=%(gpuMem)s, camera_led=%(cameraLed)s' % s)
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
if os.path.exists(CONFIG_TXT):
|
||||||
|
with open(CONFIG_TXT) as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
line = line.strip('#')
|
||||||
|
|
||||||
|
try:
|
||||||
|
name, _ = line.split('=', 1)
|
||||||
|
name = name.strip()
|
||||||
|
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
seen.add(name)
|
||||||
|
|
||||||
|
if name == 'gpu_mem':
|
||||||
|
lines[i] = '%s=%s' % (name, s['gpuMem'])
|
||||||
|
|
||||||
|
elif name == 'disable_camera_led':
|
||||||
|
lines[i] = 'disable_camera_led=%s' % ['1', '0'][s['cameraLed']]
|
||||||
|
|
||||||
|
if 'gpu_mem' not in seen:
|
||||||
|
lines.append('gpu_mem=%s' % s['gpuMem'])
|
||||||
|
|
||||||
|
if 'disable_camera_led' not in seen:
|
||||||
|
lines.append('disable_camera_led=%s' % ['1', '0'][s['cameraLed']])
|
||||||
|
|
||||||
|
logging.debug('remounting /boot read-write')
|
||||||
|
if os.system('mount -o remount,rw /boot'):
|
||||||
|
logging.error('failed to remount /boot read-write')
|
||||||
|
|
||||||
|
with open(CONFIG_TXT, 'w') as f:
|
||||||
|
for line in lines:
|
||||||
|
if not line.strip():
|
||||||
|
continue
|
||||||
|
if not line.endswith('\n'):
|
||||||
|
line += '\n'
|
||||||
|
f.write(line)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_sys_mon():
|
||||||
|
return os.access(MONITOR, os.X_OK)
|
||||||
|
|
||||||
|
|
||||||
|
def _set_sys_mon(sys_mon):
|
||||||
|
if sys_mon:
|
||||||
|
if os.access(MONITOR, os.X_OK):
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
if os.path.exists(MONITOR):
|
||||||
|
os.system('chmod +x %s' % MONITOR)
|
||||||
|
|
||||||
|
else:
|
||||||
|
with open(MONITOR, 'w') as f:
|
||||||
|
f.write(MONITOR_SCRIPT)
|
||||||
|
|
||||||
|
os.system('chmod +x %s' % MONITOR)
|
||||||
|
|
||||||
|
else:
|
||||||
|
if os.access(MONITOR, os.X_OK):
|
||||||
|
os.system('chmod -x %s' % MONITOR)
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def boardSeparator():
|
||||||
|
return {
|
||||||
|
'type': 'separator',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def gpuMem():
|
||||||
|
return {
|
||||||
|
'label': 'GPU Memory',
|
||||||
|
'description': 'set the amount of memory reserved for the GPU (choose at least 96MB if you use the CSI camera board)',
|
||||||
|
'type': 'number',
|
||||||
|
'min': '16',
|
||||||
|
'max': '944',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_board_settings,
|
||||||
|
'set': _set_board_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def cameraLed():
|
||||||
|
return {
|
||||||
|
'label': 'Enable CSI Camera Led',
|
||||||
|
'description': 'control the led on the CSI camera board',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_board_settings,
|
||||||
|
'set': _set_board_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def sysMon():
|
||||||
|
return {
|
||||||
|
'label': 'Enable System Monitoring',
|
||||||
|
'description': 'when this is enabled, system monitoring info will be overlaid on top of the first camera frame',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': False,
|
||||||
|
'get': _get_sys_mon,
|
||||||
|
'set': _set_sys_mon
|
||||||
|
}
|
||||||
|
|
1172
board/raspberrypi3/motioneye-modules/streameyectl.py
Normal file
1172
board/raspberrypi3/motioneye-modules/streameyectl.py
Normal file
File diff suppressed because it is too large
Load Diff
51
board/raspberrypi3/overlay/etc/init.d/S84streameye
Executable file
51
board/raspberrypi3/overlay/etc/init.d/S84streameye
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
motioneye_conf_dir="/data/etc/"
|
||||||
|
|
||||||
|
test -n "$os_version" || source /etc/init.d/base
|
||||||
|
|
||||||
|
enabled() {
|
||||||
|
test $(ls -1 $motioneye_conf_dir/thread-*.conf 2>/dev/null| wc -l) == 1 || return 1
|
||||||
|
|
||||||
|
grep '# @proto mjpeg' $motioneye_conf_dir/thread-1.conf &>/dev/null || return 1
|
||||||
|
|
||||||
|
grep -E '# @url http://(.*)127.0.0.1:' $motioneye_conf_dir/thread-1.conf &>/dev/null || return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled || exit 0
|
||||||
|
|
||||||
|
start() {
|
||||||
|
msg_begin "Starting streameye"
|
||||||
|
streameye.sh start
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
msg_begin "Stopping streameye"
|
||||||
|
streameye.sh stop
|
||||||
|
test $? == 0 && msg_done || msg_fail
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|restart}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit $?
|
||||||
|
|
3
board/raspberrypi3/overlay/etc/modules
Normal file
3
board/raspberrypi3/overlay/etc/modules
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
bcm2835-v4l2 max_video_width=2592 max_video_height=1944
|
||||||
|
bcm2835-wdt
|
||||||
|
|
93
board/raspberrypi3/overlay/usr/bin/streameye.sh
Executable file
93
board/raspberrypi3/overlay/usr/bin/streameye.sh
Executable file
@ -0,0 +1,93 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
RASPIMJPEG_CONF=/data/etc/raspimjpeg.conf
|
||||||
|
RASPIMJPEG_LOG=/var/log/raspimjpeg.log
|
||||||
|
MOTIONEYE_CONF=/data/etc/motioneye.conf
|
||||||
|
STREAMEYE_CONF=/data/etc/streameye.conf
|
||||||
|
STREAMEYE_LOG=/var/log/streameye.log
|
||||||
|
|
||||||
|
test -r $RASPIMJPEG_CONF || exit 1
|
||||||
|
test -r $STREAMEYE_CONF || exit 1
|
||||||
|
|
||||||
|
watch() {
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
sleep 5
|
||||||
|
if ! ps aux | grep raspimjpeg.py | grep -v grep &>/dev/null; then
|
||||||
|
logger -t streameye -s "not running, respawning"
|
||||||
|
start
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
|
if [ -n "$pid" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
raspimjpeg_opts=""
|
||||||
|
while read line; do
|
||||||
|
if echo "$line" | grep false &>/dev/null; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if echo "$line" | grep true &>/dev/null; then
|
||||||
|
line=$(echo $line | cut -d ' ' -f 1)
|
||||||
|
fi
|
||||||
|
raspimjpeg_opts="$raspimjpeg_opts --$line"
|
||||||
|
done < $RASPIMJPEG_CONF
|
||||||
|
|
||||||
|
source $STREAMEYE_CONF
|
||||||
|
streameye_opts="-p $PORT"
|
||||||
|
if [ -n "$CREDENTIALS" ] && [ "$AUTH" = "basic" ]; then
|
||||||
|
streameye_opts="$streameye_opts -a basic -c $CREDENTIALS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -r $MOTIONEYE_CONF ] && grep 'log-level debug' $MOTIONEYE_CONF >/dev/null; then
|
||||||
|
raspimjpeg_opts="$raspimjpeg_opts -d"
|
||||||
|
streameye_opts="$streameye_opts -d"
|
||||||
|
fi
|
||||||
|
|
||||||
|
raspimjpeg.py $raspimjpeg_opts 2>$RASPIMJPEG_LOG | streameye $streameye_opts &>$STREAMEYE_LOG &
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop() {
|
||||||
|
# stop the streameye background watch process
|
||||||
|
ps | grep streameye.sh | grep -v $$ | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1 | xargs -r kill
|
||||||
|
|
||||||
|
# stop the raspimjpeg process
|
||||||
|
pid=$(ps | grep raspimjpeg.py | grep -v grep | tr -s ' ' | sed -e 's/^\s//' | cut -d ' ' -f 1)
|
||||||
|
if [ -z "$pid" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
kill -HUP "$pid" &>/dev/null
|
||||||
|
count=0
|
||||||
|
while kill -0 "$pid" &>/dev/null && [ $count -lt 5 ]; do
|
||||||
|
sleep 1
|
||||||
|
count=$(($count + 1))
|
||||||
|
done
|
||||||
|
kill -KILL "$pid" &>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
watch &
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
watch &
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo $"Usage: $0 {start|stop|restart}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
@ -25,10 +25,18 @@ BR2_LINUX_KERNEL_DTS_SUPPORT=y
|
|||||||
BR2_LINUX_KERNEL_INTREE_DTS_NAME="sun7i-a20-bananapi"
|
BR2_LINUX_KERNEL_INTREE_DTS_NAME="sun7i-a20-bananapi"
|
||||||
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
||||||
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
||||||
|
BR2_PACKAGE_MOTIONEYE=y
|
||||||
BR2_PACKAGE_ALSA_UTILS=y
|
BR2_PACKAGE_ALSA_UTILS=y
|
||||||
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
||||||
|
BR2_PACKAGE_FFMPEG=y
|
||||||
|
BR2_PACKAGE_FFMPEG_GPL=y
|
||||||
|
BR2_PACKAGE_FFMPEG_NONFREE=y
|
||||||
|
BR2_PACKAGE_FFMPEG_SWSCALE=y
|
||||||
|
BR2_PACKAGE_LIBWEBCAM=y
|
||||||
|
BR2_PACKAGE_MOTION=y
|
||||||
BR2_PACKAGE_GZIP=y
|
BR2_PACKAGE_GZIP=y
|
||||||
BR2_PACKAGE_JQ=y
|
BR2_PACKAGE_JQ=y
|
||||||
|
BR2_PACKAGE_CIFS_UTILS=y
|
||||||
BR2_PACKAGE_E2FSPROGS=y
|
BR2_PACKAGE_E2FSPROGS=y
|
||||||
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
||||||
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
||||||
@ -62,9 +70,23 @@ BR2_PACKAGE_LINUX_FIRMWARE_RTL_88XX=y
|
|||||||
BR2_PACKAGE_SUNXI_BOARDS=y
|
BR2_PACKAGE_SUNXI_BOARDS=y
|
||||||
BR2_PACKAGE_SUNXI_BOARDS_FEX_FILE="a20/Bananapi.fex"
|
BR2_PACKAGE_SUNXI_BOARDS_FEX_FILE="a20/Bananapi.fex"
|
||||||
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
||||||
|
BR2_PACKAGE_PYTHON_SSL=y
|
||||||
|
BR2_PACKAGE_PYTHON_HASHLIB=y
|
||||||
|
BR2_PACKAGE_PYTHON_JINJA2=y
|
||||||
|
BR2_PACKAGE_PYTHON_PILLOW=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYCURL=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYTZ=y
|
||||||
|
BR2_PACKAGE_PYTHON_TORNADO=y
|
||||||
|
BR2_PACKAGE_PYTHON_VERSIONTOOLS=y
|
||||||
BR2_PACKAGE_CA_CERTIFICATES=y
|
BR2_PACKAGE_CA_CERTIFICATES=y
|
||||||
BR2_PACKAGE_NETTLE=y
|
BR2_PACKAGE_NETTLE=y
|
||||||
BR2_PACKAGE_LIBFUSE=y
|
BR2_PACKAGE_LIBFUSE=y
|
||||||
|
BR2_PACKAGE_LIBV4L=y
|
||||||
|
BR2_PACKAGE_LIBV4L_UTILS=y
|
||||||
|
BR2_PACKAGE_LIBXML2=y
|
||||||
|
BR2_PACKAGE_LIBTHEORA=y
|
||||||
|
BR2_PACKAGE_X264=y
|
||||||
|
BR2_PACKAGE_X265=y
|
||||||
BR2_PACKAGE_LIBCURL=y
|
BR2_PACKAGE_LIBCURL=y
|
||||||
BR2_PACKAGE_CURL=y
|
BR2_PACKAGE_CURL=y
|
||||||
BR2_PACKAGE_LIBCAP=y
|
BR2_PACKAGE_LIBCAP=y
|
||||||
@ -81,6 +103,9 @@ BR2_PACKAGE_NTP=y
|
|||||||
BR2_PACKAGE_NTP_NTPDATE=y
|
BR2_PACKAGE_NTP_NTPDATE=y
|
||||||
BR2_PACKAGE_OPENSSH=y
|
BR2_PACKAGE_OPENSSH=y
|
||||||
BR2_PACKAGE_PPPD=y
|
BR2_PACKAGE_PPPD=y
|
||||||
|
BR2_PACKAGE_PROFTPD=y
|
||||||
|
BR2_PACKAGE_RSYNC=y
|
||||||
|
BR2_PACKAGE_SAMBA4=y
|
||||||
BR2_PACKAGE_WGET=y
|
BR2_PACKAGE_WGET=y
|
||||||
BR2_PACKAGE_WIRELESS_TOOLS=y
|
BR2_PACKAGE_WIRELESS_TOOLS=y
|
||||||
BR2_PACKAGE_WPA_SUPPLICANT=y
|
BR2_PACKAGE_WPA_SUPPLICANT=y
|
||||||
|
@ -32,10 +32,17 @@ BR2_LINUX_KERNEL_DTS_SUPPORT=y
|
|||||||
BR2_LINUX_KERNEL_INTREE_DTS_NAME="meson8b_odroidc"
|
BR2_LINUX_KERNEL_INTREE_DTS_NAME="meson8b_odroidc"
|
||||||
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
||||||
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
||||||
|
BR2_PACKAGE_MOTIONEYE=y
|
||||||
BR2_PACKAGE_ALSA_UTILS=y
|
BR2_PACKAGE_ALSA_UTILS=y
|
||||||
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
||||||
|
BR2_PACKAGE_FFMPEG=y
|
||||||
|
BR2_PACKAGE_FFMPEG_GPL=y
|
||||||
|
BR2_PACKAGE_FFMPEG_NONFREE=y
|
||||||
|
BR2_PACKAGE_FFMPEG_SWSCALE=y
|
||||||
|
BR2_PACKAGE_MOTION=y
|
||||||
BR2_PACKAGE_GZIP=y
|
BR2_PACKAGE_GZIP=y
|
||||||
BR2_PACKAGE_JQ=y
|
BR2_PACKAGE_JQ=y
|
||||||
|
BR2_PACKAGE_CIFS_UTILS=y
|
||||||
BR2_PACKAGE_E2FSPROGS=y
|
BR2_PACKAGE_E2FSPROGS=y
|
||||||
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
||||||
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
||||||
@ -67,9 +74,23 @@ BR2_PACKAGE_LINUX_FIRMWARE_RTL_81XX=y
|
|||||||
BR2_PACKAGE_LINUX_FIRMWARE_RTL_87XX=y
|
BR2_PACKAGE_LINUX_FIRMWARE_RTL_87XX=y
|
||||||
BR2_PACKAGE_LINUX_FIRMWARE_RTL_88XX=y
|
BR2_PACKAGE_LINUX_FIRMWARE_RTL_88XX=y
|
||||||
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
||||||
|
BR2_PACKAGE_PYTHON_SSL=y
|
||||||
|
BR2_PACKAGE_PYTHON_HASHLIB=y
|
||||||
|
BR2_PACKAGE_PYTHON_JINJA2=y
|
||||||
|
BR2_PACKAGE_PYTHON_PILLOW=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYCURL=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYTZ=y
|
||||||
|
BR2_PACKAGE_PYTHON_TORNADO=y
|
||||||
|
BR2_PACKAGE_PYTHON_VERSIONTOOLS=y
|
||||||
BR2_PACKAGE_CA_CERTIFICATES=y
|
BR2_PACKAGE_CA_CERTIFICATES=y
|
||||||
BR2_PACKAGE_NETTLE=y
|
BR2_PACKAGE_NETTLE=y
|
||||||
BR2_PACKAGE_LIBFUSE=y
|
BR2_PACKAGE_LIBFUSE=y
|
||||||
|
BR2_PACKAGE_LIBV4L=y
|
||||||
|
BR2_PACKAGE_LIBV4L_UTILS=y
|
||||||
|
BR2_PACKAGE_LIBXML2=y
|
||||||
|
BR2_PACKAGE_LIBTHEORA=y
|
||||||
|
BR2_PACKAGE_X264=y
|
||||||
|
BR2_PACKAGE_X265=y
|
||||||
BR2_PACKAGE_LIBCURL=y
|
BR2_PACKAGE_LIBCURL=y
|
||||||
BR2_PACKAGE_CURL=y
|
BR2_PACKAGE_CURL=y
|
||||||
BR2_PACKAGE_LIBCAP=y
|
BR2_PACKAGE_LIBCAP=y
|
||||||
@ -86,6 +107,9 @@ BR2_PACKAGE_NTP=y
|
|||||||
BR2_PACKAGE_NTP_NTPDATE=y
|
BR2_PACKAGE_NTP_NTPDATE=y
|
||||||
BR2_PACKAGE_OPENSSH=y
|
BR2_PACKAGE_OPENSSH=y
|
||||||
BR2_PACKAGE_PPPD=y
|
BR2_PACKAGE_PPPD=y
|
||||||
|
BR2_PACKAGE_PROFTPD=y
|
||||||
|
BR2_PACKAGE_RSYNC=y
|
||||||
|
BR2_PACKAGE_SAMBA4=y
|
||||||
BR2_PACKAGE_WGET=y
|
BR2_PACKAGE_WGET=y
|
||||||
BR2_PACKAGE_WIRELESS_TOOLS=y
|
BR2_PACKAGE_WIRELESS_TOOLS=y
|
||||||
BR2_PACKAGE_WPA_SUPPLICANT=y
|
BR2_PACKAGE_WPA_SUPPLICANT=y
|
||||||
|
@ -21,10 +21,17 @@ BR2_LINUX_KERNEL_DTS_SUPPORT=y
|
|||||||
BR2_LINUX_KERNEL_INTREE_DTS_NAME="meson64_odroidc2"
|
BR2_LINUX_KERNEL_INTREE_DTS_NAME="meson64_odroidc2"
|
||||||
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
||||||
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
||||||
|
BR2_PACKAGE_MOTIONEYE=y
|
||||||
BR2_PACKAGE_ALSA_UTILS=y
|
BR2_PACKAGE_ALSA_UTILS=y
|
||||||
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
||||||
|
BR2_PACKAGE_FFMPEG=y
|
||||||
|
BR2_PACKAGE_FFMPEG_GPL=y
|
||||||
|
BR2_PACKAGE_FFMPEG_NONFREE=y
|
||||||
|
BR2_PACKAGE_FFMPEG_SWSCALE=y
|
||||||
|
BR2_PACKAGE_MOTION=y
|
||||||
BR2_PACKAGE_GZIP=y
|
BR2_PACKAGE_GZIP=y
|
||||||
BR2_PACKAGE_JQ=y
|
BR2_PACKAGE_JQ=y
|
||||||
|
BR2_PACKAGE_CIFS_UTILS=y
|
||||||
BR2_PACKAGE_E2FSPROGS=y
|
BR2_PACKAGE_E2FSPROGS=y
|
||||||
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
||||||
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
||||||
@ -56,9 +63,24 @@ BR2_PACKAGE_LINUX_FIRMWARE_RTL_81XX=y
|
|||||||
BR2_PACKAGE_LINUX_FIRMWARE_RTL_87XX=y
|
BR2_PACKAGE_LINUX_FIRMWARE_RTL_87XX=y
|
||||||
BR2_PACKAGE_LINUX_FIRMWARE_RTL_88XX=y
|
BR2_PACKAGE_LINUX_FIRMWARE_RTL_88XX=y
|
||||||
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
||||||
|
BR2_PACKAGE_PYTHON_SSL=y
|
||||||
|
BR2_PACKAGE_PYTHON_HASHLIB=y
|
||||||
|
BR2_PACKAGE_PYTHON_JINJA2=y
|
||||||
|
BR2_PACKAGE_PYTHON_PILLOW=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYCURL=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYTZ=y
|
||||||
|
BR2_PACKAGE_PYTHON_TORNADO=y
|
||||||
|
BR2_PACKAGE_PYTHON_VERSIONTOOLS=y
|
||||||
BR2_PACKAGE_CA_CERTIFICATES=y
|
BR2_PACKAGE_CA_CERTIFICATES=y
|
||||||
BR2_PACKAGE_NETTLE=y
|
BR2_PACKAGE_NETTLE=y
|
||||||
BR2_PACKAGE_LIBFUSE=y
|
BR2_PACKAGE_LIBFUSE=y
|
||||||
|
BR2_PACKAGE_JPEG_TURBO=y
|
||||||
|
BR2_PACKAGE_LIBV4L=y
|
||||||
|
BR2_PACKAGE_LIBV4L_UTILS=y
|
||||||
|
BR2_PACKAGE_LIBXML2=y
|
||||||
|
BR2_PACKAGE_LIBTHEORA=y
|
||||||
|
BR2_PACKAGE_X264=y
|
||||||
|
BR2_PACKAGE_X265=y
|
||||||
BR2_PACKAGE_LIBCURL=y
|
BR2_PACKAGE_LIBCURL=y
|
||||||
BR2_PACKAGE_CURL=y
|
BR2_PACKAGE_CURL=y
|
||||||
BR2_PACKAGE_LIBCAP=y
|
BR2_PACKAGE_LIBCAP=y
|
||||||
@ -75,6 +97,9 @@ BR2_PACKAGE_NTP=y
|
|||||||
BR2_PACKAGE_NTP_NTPDATE=y
|
BR2_PACKAGE_NTP_NTPDATE=y
|
||||||
BR2_PACKAGE_OPENSSH=y
|
BR2_PACKAGE_OPENSSH=y
|
||||||
BR2_PACKAGE_PPPD=y
|
BR2_PACKAGE_PPPD=y
|
||||||
|
BR2_PACKAGE_PROFTPD=y
|
||||||
|
BR2_PACKAGE_RSYNC=y
|
||||||
|
BR2_PACKAGE_SAMBA4=y
|
||||||
BR2_PACKAGE_WGET=y
|
BR2_PACKAGE_WGET=y
|
||||||
BR2_PACKAGE_WIRELESS_TOOLS=y
|
BR2_PACKAGE_WIRELESS_TOOLS=y
|
||||||
BR2_PACKAGE_WPA_SUPPLICANT=y
|
BR2_PACKAGE_WPA_SUPPLICANT=y
|
||||||
|
@ -23,10 +23,17 @@ BR2_LINUX_KERNEL_DTS_SUPPORT=y
|
|||||||
BR2_LINUX_KERNEL_INTREE_DTS_NAME="exynos5422-odroidxu3"
|
BR2_LINUX_KERNEL_INTREE_DTS_NAME="exynos5422-odroidxu3"
|
||||||
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
||||||
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
||||||
|
BR2_PACKAGE_MOTIONEYE=y
|
||||||
BR2_PACKAGE_ALSA_UTILS=y
|
BR2_PACKAGE_ALSA_UTILS=y
|
||||||
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
||||||
|
BR2_PACKAGE_FFMPEG=y
|
||||||
|
BR2_PACKAGE_FFMPEG_GPL=y
|
||||||
|
BR2_PACKAGE_FFMPEG_NONFREE=y
|
||||||
|
BR2_PACKAGE_FFMPEG_SWSCALE=y
|
||||||
|
BR2_PACKAGE_MOTION=y
|
||||||
BR2_PACKAGE_GZIP=y
|
BR2_PACKAGE_GZIP=y
|
||||||
BR2_PACKAGE_JQ=y
|
BR2_PACKAGE_JQ=y
|
||||||
|
BR2_PACKAGE_CIFS_UTILS=y
|
||||||
BR2_PACKAGE_E2FSPROGS=y
|
BR2_PACKAGE_E2FSPROGS=y
|
||||||
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
||||||
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
||||||
@ -58,9 +65,23 @@ BR2_PACKAGE_LINUX_FIRMWARE_RTL_81XX=y
|
|||||||
BR2_PACKAGE_LINUX_FIRMWARE_RTL_87XX=y
|
BR2_PACKAGE_LINUX_FIRMWARE_RTL_87XX=y
|
||||||
BR2_PACKAGE_LINUX_FIRMWARE_RTL_88XX=y
|
BR2_PACKAGE_LINUX_FIRMWARE_RTL_88XX=y
|
||||||
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
||||||
|
BR2_PACKAGE_PYTHON_SSL=y
|
||||||
|
BR2_PACKAGE_PYTHON_HASHLIB=y
|
||||||
|
BR2_PACKAGE_PYTHON_JINJA2=y
|
||||||
|
BR2_PACKAGE_PYTHON_PILLOW=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYCURL=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYTZ=y
|
||||||
|
BR2_PACKAGE_PYTHON_TORNADO=y
|
||||||
|
BR2_PACKAGE_PYTHON_VERSIONTOOLS=y
|
||||||
BR2_PACKAGE_CA_CERTIFICATES=y
|
BR2_PACKAGE_CA_CERTIFICATES=y
|
||||||
BR2_PACKAGE_NETTLE=y
|
BR2_PACKAGE_NETTLE=y
|
||||||
BR2_PACKAGE_LIBFUSE=y
|
BR2_PACKAGE_LIBFUSE=y
|
||||||
|
BR2_PACKAGE_LIBV4L=y
|
||||||
|
BR2_PACKAGE_LIBV4L_UTILS=y
|
||||||
|
BR2_PACKAGE_LIBXML2=y
|
||||||
|
BR2_PACKAGE_LIBTHEORA=y
|
||||||
|
BR2_PACKAGE_X264=y
|
||||||
|
BR2_PACKAGE_X265=y
|
||||||
BR2_PACKAGE_LIBCURL=y
|
BR2_PACKAGE_LIBCURL=y
|
||||||
BR2_PACKAGE_CURL=y
|
BR2_PACKAGE_CURL=y
|
||||||
BR2_PACKAGE_LIBCAP=y
|
BR2_PACKAGE_LIBCAP=y
|
||||||
@ -77,6 +98,9 @@ BR2_PACKAGE_NTP=y
|
|||||||
BR2_PACKAGE_NTP_NTPDATE=y
|
BR2_PACKAGE_NTP_NTPDATE=y
|
||||||
BR2_PACKAGE_OPENSSH=y
|
BR2_PACKAGE_OPENSSH=y
|
||||||
BR2_PACKAGE_PPPD=y
|
BR2_PACKAGE_PPPD=y
|
||||||
|
BR2_PACKAGE_PROFTPD=y
|
||||||
|
BR2_PACKAGE_RSYNC=y
|
||||||
|
BR2_PACKAGE_SAMBA4=y
|
||||||
BR2_PACKAGE_WGET=y
|
BR2_PACKAGE_WGET=y
|
||||||
BR2_PACKAGE_WIRELESS_TOOLS=y
|
BR2_PACKAGE_WIRELESS_TOOLS=y
|
||||||
BR2_PACKAGE_WPA_SUPPLICANT=y
|
BR2_PACKAGE_WPA_SUPPLICANT=y
|
||||||
|
@ -23,10 +23,20 @@ BR2_LINUX_KERNEL_DTS_SUPPORT=y
|
|||||||
BR2_LINUX_KERNEL_INTREE_DTS_NAME="bcm2709-rpi-2-b"
|
BR2_LINUX_KERNEL_INTREE_DTS_NAME="bcm2709-rpi-2-b"
|
||||||
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
||||||
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
||||||
|
BR2_PACKAGE_MOTIONEYE=y
|
||||||
BR2_PACKAGE_ALSA_UTILS=y
|
BR2_PACKAGE_ALSA_UTILS=y
|
||||||
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
||||||
|
BR2_PACKAGE_FFMPEG=y
|
||||||
|
BR2_PACKAGE_FFMPEG_GPL=y
|
||||||
|
BR2_PACKAGE_FFMPEG_NONFREE=y
|
||||||
|
BR2_PACKAGE_FFMPEG_SWSCALE=y
|
||||||
|
BR2_PACKAGE_LIBWEBCAM=y
|
||||||
|
BR2_PACKAGE_MOTION=y
|
||||||
|
BR2_PACKAGE_MOTION_MMAL=y
|
||||||
|
BR2_PACKAGE_STREAMEYE=y
|
||||||
BR2_PACKAGE_GZIP=y
|
BR2_PACKAGE_GZIP=y
|
||||||
BR2_PACKAGE_JQ=y
|
BR2_PACKAGE_JQ=y
|
||||||
|
BR2_PACKAGE_CIFS_UTILS=y
|
||||||
BR2_PACKAGE_E2FSPROGS=y
|
BR2_PACKAGE_E2FSPROGS=y
|
||||||
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
||||||
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
||||||
@ -61,9 +71,25 @@ BR2_PACKAGE_RPI_FIRMWARE=y
|
|||||||
BR2_PACKAGE_RPI_FIRMWARE_X=y
|
BR2_PACKAGE_RPI_FIRMWARE_X=y
|
||||||
BR2_PACKAGE_RPI_USERLAND=y
|
BR2_PACKAGE_RPI_USERLAND=y
|
||||||
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
||||||
|
BR2_PACKAGE_PYTHON_SSL=y
|
||||||
|
BR2_PACKAGE_PYTHON_HASHLIB=y
|
||||||
|
BR2_PACKAGE_PYTHON_JINJA2=y
|
||||||
|
BR2_PACKAGE_PYTHON_PICAMERA=y
|
||||||
|
BR2_PACKAGE_PYTHON_PILLOW=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYCURL=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYTZ=y
|
||||||
|
BR2_PACKAGE_PYTHON_RPI_GPIO=y
|
||||||
|
BR2_PACKAGE_PYTHON_TORNADO=y
|
||||||
|
BR2_PACKAGE_PYTHON_VERSIONTOOLS=y
|
||||||
BR2_PACKAGE_CA_CERTIFICATES=y
|
BR2_PACKAGE_CA_CERTIFICATES=y
|
||||||
BR2_PACKAGE_NETTLE=y
|
BR2_PACKAGE_NETTLE=y
|
||||||
BR2_PACKAGE_LIBFUSE=y
|
BR2_PACKAGE_LIBFUSE=y
|
||||||
|
BR2_PACKAGE_LIBV4L=y
|
||||||
|
BR2_PACKAGE_LIBV4L_UTILS=y
|
||||||
|
BR2_PACKAGE_LIBXML2=y
|
||||||
|
BR2_PACKAGE_LIBTHEORA=y
|
||||||
|
BR2_PACKAGE_X264=y
|
||||||
|
BR2_PACKAGE_X265=y
|
||||||
BR2_PACKAGE_LIBCURL=y
|
BR2_PACKAGE_LIBCURL=y
|
||||||
BR2_PACKAGE_CURL=y
|
BR2_PACKAGE_CURL=y
|
||||||
BR2_PACKAGE_LIBCAP=y
|
BR2_PACKAGE_LIBCAP=y
|
||||||
@ -80,6 +106,9 @@ BR2_PACKAGE_NTP=y
|
|||||||
BR2_PACKAGE_NTP_NTPDATE=y
|
BR2_PACKAGE_NTP_NTPDATE=y
|
||||||
BR2_PACKAGE_OPENSSH=y
|
BR2_PACKAGE_OPENSSH=y
|
||||||
BR2_PACKAGE_PPPD=y
|
BR2_PACKAGE_PPPD=y
|
||||||
|
BR2_PACKAGE_PROFTPD=y
|
||||||
|
BR2_PACKAGE_RSYNC=y
|
||||||
|
BR2_PACKAGE_SAMBA4=y
|
||||||
BR2_PACKAGE_WGET=y
|
BR2_PACKAGE_WGET=y
|
||||||
BR2_PACKAGE_WIRELESS_TOOLS=y
|
BR2_PACKAGE_WIRELESS_TOOLS=y
|
||||||
BR2_PACKAGE_WPA_SUPPLICANT=y
|
BR2_PACKAGE_WPA_SUPPLICANT=y
|
||||||
|
@ -23,10 +23,20 @@ BR2_LINUX_KERNEL_DTS_SUPPORT=y
|
|||||||
BR2_LINUX_KERNEL_INTREE_DTS_NAME="bcm2710-rpi-3-b"
|
BR2_LINUX_KERNEL_INTREE_DTS_NAME="bcm2710-rpi-3-b"
|
||||||
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
||||||
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
||||||
|
BR2_PACKAGE_MOTIONEYE=y
|
||||||
BR2_PACKAGE_ALSA_UTILS=y
|
BR2_PACKAGE_ALSA_UTILS=y
|
||||||
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
||||||
|
BR2_PACKAGE_FFMPEG=y
|
||||||
|
BR2_PACKAGE_FFMPEG_GPL=y
|
||||||
|
BR2_PACKAGE_FFMPEG_NONFREE=y
|
||||||
|
BR2_PACKAGE_FFMPEG_SWSCALE=y
|
||||||
|
BR2_PACKAGE_LIBWEBCAM=y
|
||||||
|
BR2_PACKAGE_MOTION=y
|
||||||
|
BR2_PACKAGE_MOTION_MMAL=y
|
||||||
|
BR2_PACKAGE_STREAMEYE=y
|
||||||
BR2_PACKAGE_GZIP=y
|
BR2_PACKAGE_GZIP=y
|
||||||
BR2_PACKAGE_JQ=y
|
BR2_PACKAGE_JQ=y
|
||||||
|
BR2_PACKAGE_CIFS_UTILS=y
|
||||||
BR2_PACKAGE_E2FSPROGS=y
|
BR2_PACKAGE_E2FSPROGS=y
|
||||||
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
||||||
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
||||||
@ -61,9 +71,25 @@ BR2_PACKAGE_RPI_FIRMWARE=y
|
|||||||
BR2_PACKAGE_RPI_FIRMWARE_X=y
|
BR2_PACKAGE_RPI_FIRMWARE_X=y
|
||||||
BR2_PACKAGE_RPI_USERLAND=y
|
BR2_PACKAGE_RPI_USERLAND=y
|
||||||
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
||||||
|
BR2_PACKAGE_PYTHON_SSL=y
|
||||||
|
BR2_PACKAGE_PYTHON_HASHLIB=y
|
||||||
|
BR2_PACKAGE_PYTHON_JINJA2=y
|
||||||
|
BR2_PACKAGE_PYTHON_PICAMERA=y
|
||||||
|
BR2_PACKAGE_PYTHON_PILLOW=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYCURL=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYTZ=y
|
||||||
|
BR2_PACKAGE_PYTHON_RPI_GPIO=y
|
||||||
|
BR2_PACKAGE_PYTHON_TORNADO=y
|
||||||
|
BR2_PACKAGE_PYTHON_VERSIONTOOLS=y
|
||||||
BR2_PACKAGE_CA_CERTIFICATES=y
|
BR2_PACKAGE_CA_CERTIFICATES=y
|
||||||
BR2_PACKAGE_NETTLE=y
|
BR2_PACKAGE_NETTLE=y
|
||||||
BR2_PACKAGE_LIBFUSE=y
|
BR2_PACKAGE_LIBFUSE=y
|
||||||
|
BR2_PACKAGE_LIBV4L=y
|
||||||
|
BR2_PACKAGE_LIBV4L_UTILS=y
|
||||||
|
BR2_PACKAGE_LIBXML2=y
|
||||||
|
BR2_PACKAGE_LIBTHEORA=y
|
||||||
|
BR2_PACKAGE_X264=y
|
||||||
|
BR2_PACKAGE_X265=y
|
||||||
BR2_PACKAGE_LIBCURL=y
|
BR2_PACKAGE_LIBCURL=y
|
||||||
BR2_PACKAGE_CURL=y
|
BR2_PACKAGE_CURL=y
|
||||||
BR2_PACKAGE_LIBCAP=y
|
BR2_PACKAGE_LIBCAP=y
|
||||||
@ -80,6 +106,9 @@ BR2_PACKAGE_NTP=y
|
|||||||
BR2_PACKAGE_NTP_NTPDATE=y
|
BR2_PACKAGE_NTP_NTPDATE=y
|
||||||
BR2_PACKAGE_OPENSSH=y
|
BR2_PACKAGE_OPENSSH=y
|
||||||
BR2_PACKAGE_PPPD=y
|
BR2_PACKAGE_PPPD=y
|
||||||
|
BR2_PACKAGE_PROFTPD=y
|
||||||
|
BR2_PACKAGE_RSYNC=y
|
||||||
|
BR2_PACKAGE_SAMBA4=y
|
||||||
BR2_PACKAGE_WGET=y
|
BR2_PACKAGE_WGET=y
|
||||||
BR2_PACKAGE_WIRELESS_TOOLS=y
|
BR2_PACKAGE_WIRELESS_TOOLS=y
|
||||||
BR2_PACKAGE_WPA_SUPPLICANT=y
|
BR2_PACKAGE_WPA_SUPPLICANT=y
|
||||||
|
@ -27,10 +27,20 @@ BR2_LINUX_KERNEL_DTS_SUPPORT=y
|
|||||||
BR2_LINUX_KERNEL_INTREE_DTS_NAME="bcm2708-rpi-b bcm2708-rpi-b-plus bcm2708-rpi-cm"
|
BR2_LINUX_KERNEL_INTREE_DTS_NAME="bcm2708-rpi-b bcm2708-rpi-b-plus bcm2708-rpi-cm"
|
||||||
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
BR2_PACKAGE_BUSYBOX_CONFIG="board/common/busybox.config"
|
||||||
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
|
||||||
|
BR2_PACKAGE_MOTIONEYE=y
|
||||||
BR2_PACKAGE_ALSA_UTILS=y
|
BR2_PACKAGE_ALSA_UTILS=y
|
||||||
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
BR2_PACKAGE_ALSA_UTILS_APLAY=y
|
||||||
|
BR2_PACKAGE_FFMPEG=y
|
||||||
|
BR2_PACKAGE_FFMPEG_GPL=y
|
||||||
|
BR2_PACKAGE_FFMPEG_NONFREE=y
|
||||||
|
BR2_PACKAGE_FFMPEG_SWSCALE=y
|
||||||
|
BR2_PACKAGE_LIBWEBCAM=y
|
||||||
|
BR2_PACKAGE_MOTION=y
|
||||||
|
BR2_PACKAGE_MOTION_MMAL=y
|
||||||
|
BR2_PACKAGE_STREAMEYE=y
|
||||||
BR2_PACKAGE_GZIP=y
|
BR2_PACKAGE_GZIP=y
|
||||||
BR2_PACKAGE_JQ=y
|
BR2_PACKAGE_JQ=y
|
||||||
|
BR2_PACKAGE_CIFS_UTILS=y
|
||||||
BR2_PACKAGE_E2FSPROGS=y
|
BR2_PACKAGE_E2FSPROGS=y
|
||||||
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
# BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set
|
||||||
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
# BR2_PACKAGE_E2FSPROGS_CHATTR is not set
|
||||||
@ -66,9 +76,26 @@ BR2_PACKAGE_RPI_FIRMWARE_X=y
|
|||||||
BR2_PACKAGE_RPI_ARMMEM=y
|
BR2_PACKAGE_RPI_ARMMEM=y
|
||||||
BR2_PACKAGE_RPI_USERLAND=y
|
BR2_PACKAGE_RPI_USERLAND=y
|
||||||
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
BR2_PACKAGE_USB_MODESWITCH_DATA=y
|
||||||
|
BR2_PACKAGE_PYTHON_SSL=y
|
||||||
|
BR2_PACKAGE_PYTHON_HASHLIB=y
|
||||||
|
BR2_PACKAGE_PYTHON_JINJA2=y
|
||||||
|
BR2_PACKAGE_PYTHON_PICAMERA=y
|
||||||
|
BR2_PACKAGE_PYTHON_PILLOW=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYCURL=y
|
||||||
|
BR2_PACKAGE_PYTHON_PYTZ=y
|
||||||
|
BR2_PACKAGE_PYTHON_RPI_GPIO=y
|
||||||
|
BR2_PACKAGE_PYTHON_TORNADO=y
|
||||||
|
BR2_PACKAGE_PYTHON_VERSIONTOOLS=y
|
||||||
BR2_PACKAGE_CA_CERTIFICATES=y
|
BR2_PACKAGE_CA_CERTIFICATES=y
|
||||||
BR2_PACKAGE_NETTLE=y
|
BR2_PACKAGE_NETTLE=y
|
||||||
BR2_PACKAGE_LIBFUSE=y
|
BR2_PACKAGE_LIBFUSE=y
|
||||||
|
BR2_PACKAGE_JPEG_TURBO=y
|
||||||
|
BR2_PACKAGE_LIBV4L=y
|
||||||
|
BR2_PACKAGE_LIBV4L_UTILS=y
|
||||||
|
BR2_PACKAGE_LIBXML2=y
|
||||||
|
BR2_PACKAGE_LIBTHEORA=y
|
||||||
|
BR2_PACKAGE_X264=y
|
||||||
|
BR2_PACKAGE_X265=y
|
||||||
BR2_PACKAGE_LIBCURL=y
|
BR2_PACKAGE_LIBCURL=y
|
||||||
BR2_PACKAGE_CURL=y
|
BR2_PACKAGE_CURL=y
|
||||||
BR2_PACKAGE_LIBCAP=y
|
BR2_PACKAGE_LIBCAP=y
|
||||||
@ -85,6 +112,9 @@ BR2_PACKAGE_NTP=y
|
|||||||
BR2_PACKAGE_NTP_NTPDATE=y
|
BR2_PACKAGE_NTP_NTPDATE=y
|
||||||
BR2_PACKAGE_OPENSSH=y
|
BR2_PACKAGE_OPENSSH=y
|
||||||
BR2_PACKAGE_PPPD=y
|
BR2_PACKAGE_PPPD=y
|
||||||
|
BR2_PACKAGE_PROFTPD=y
|
||||||
|
BR2_PACKAGE_RSYNC=y
|
||||||
|
BR2_PACKAGE_SAMBA4=y
|
||||||
BR2_PACKAGE_WGET=y
|
BR2_PACKAGE_WGET=y
|
||||||
BR2_PACKAGE_WIRELESS_TOOLS=y
|
BR2_PACKAGE_WIRELESS_TOOLS=y
|
||||||
BR2_PACKAGE_WPA_SUPPLICANT=y
|
BR2_PACKAGE_WPA_SUPPLICANT=y
|
||||||
|
@ -2,6 +2,7 @@ menu "Target packages"
|
|||||||
|
|
||||||
source "package/busybox/Config.in"
|
source "package/busybox/Config.in"
|
||||||
source "package/skeleton/Config.in"
|
source "package/skeleton/Config.in"
|
||||||
|
source "package/motioneye/Config.in"
|
||||||
|
|
||||||
menu "Audio and video applications"
|
menu "Audio and video applications"
|
||||||
source "package/alsa-utils/Config.in"
|
source "package/alsa-utils/Config.in"
|
||||||
@ -21,9 +22,11 @@ menu "Audio and video applications"
|
|||||||
source "package/jack2/Config.in"
|
source "package/jack2/Config.in"
|
||||||
source "package/kodi/Config.in"
|
source "package/kodi/Config.in"
|
||||||
source "package/lame/Config.in"
|
source "package/lame/Config.in"
|
||||||
|
source "package/libwebcam/Config.in"
|
||||||
source "package/madplay/Config.in"
|
source "package/madplay/Config.in"
|
||||||
source "package/miraclecast/Config.in"
|
source "package/miraclecast/Config.in"
|
||||||
source "package/mjpegtools/Config.in"
|
source "package/mjpegtools/Config.in"
|
||||||
|
source "package/motion/Config.in"
|
||||||
source "package/modplugtools/Config.in"
|
source "package/modplugtools/Config.in"
|
||||||
source "package/mpd/Config.in"
|
source "package/mpd/Config.in"
|
||||||
source "package/mpd-mpc/Config.in"
|
source "package/mpd-mpc/Config.in"
|
||||||
@ -37,6 +40,7 @@ menu "Audio and video applications"
|
|||||||
source "package/opus-tools/Config.in"
|
source "package/opus-tools/Config.in"
|
||||||
source "package/pulseaudio/Config.in"
|
source "package/pulseaudio/Config.in"
|
||||||
source "package/sox/Config.in"
|
source "package/sox/Config.in"
|
||||||
|
source "package/streameye/Config.in"
|
||||||
source "package/squeezelite/Config.in"
|
source "package/squeezelite/Config.in"
|
||||||
source "package/tidsp-binaries/Config.in"
|
source "package/tidsp-binaries/Config.in"
|
||||||
source "package/tovid/Config.in"
|
source "package/tovid/Config.in"
|
||||||
|
3
package/libwebcam/Config.in
Normal file
3
package/libwebcam/Config.in
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
config BR2_PACKAGE_LIBWEBCAM
|
||||||
|
bool "libwebcam"
|
||||||
|
|
18
package/libwebcam/libwebcam.mk
Normal file
18
package/libwebcam/libwebcam.mk
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# libwebcam
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
LIBWEBCAM_VERSION = 0.2.5
|
||||||
|
LIBWEBCAM_SOURCE = libwebcam-src-$(LIBWEBCAM_VERSION).tar.gz
|
||||||
|
LIBWEBCAM_SITE = http://freefr.dl.sourceforge.net/project/libwebcam/source
|
||||||
|
LIBWEBCAM_DEPENDENCIES = libxml2
|
||||||
|
|
||||||
|
define LIBWEBCAM_INSTALL_TARGET_CMDS
|
||||||
|
rm $(@D)/uvcdynctrl/uvcdynctrl-*.gz
|
||||||
|
cp $(@D)/uvcdynctrl/uvcdynctrl $(TARGET_DIR)/usr/bin/uvcdynctrl
|
||||||
|
cp -d $(@D)/libwebcam/libwebcam.so* $(TARGET_DIR)/usr/lib
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(cmake-package))
|
16
package/motion/0001-version.patch
Normal file
16
package/motion/0001-version.patch
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
diff -uNr motion/version.sh motion.new/version.sh
|
||||||
|
--- motion/version.sh 2016-11-13 12:45:14.143548855 +0200
|
||||||
|
+++ motion.new/version.sh 2016-11-13 12:45:31.683635991 +0200
|
||||||
|
@@ -1,8 +1,9 @@
|
||||||
|
#!/bin/sh
|
||||||
|
BASE_VERSION="4.0.1"
|
||||||
|
if [ -d .git ]; then
|
||||||
|
- GIT_COMMIT=`git show -s --format=%h`
|
||||||
|
- printf "$BASE_VERSION+git$GIT_COMMIT"
|
||||||
|
+ GIT_COMMIT=`git show -s --format=%h`
|
||||||
|
+ printf "$BASE_VERSION+git$GIT_COMMIT"
|
||||||
|
else
|
||||||
|
- printf "$BASE_VERSION+gitUNKNOWN"
|
||||||
|
+ printf "$BASE_VERSION+git$(basename $(pwd) | cut -d '-' -f 2)"
|
||||||
|
fi
|
||||||
|
+
|
3
package/motion/Config.in
Normal file
3
package/motion/Config.in
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
config BR2_PACKAGE_MOTION
|
||||||
|
bool "motion"
|
||||||
|
help
|
18
package/motion/motion.mk
Normal file
18
package/motion/motion.mk
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# motion
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
MOTION_VERSION = 37b3595
|
||||||
|
MOTION_SITE = $(call github,motion-project,motion,$(MOTION_VERSION))
|
||||||
|
MOTION_AUTORECONF = YES
|
||||||
|
MOTION_CONF_OPTS = --without-pgsql --without-sdl --without-sqlite3 --without-mysql --with-ffmpeg=$(STAGING_DIR)/usr/lib \
|
||||||
|
--with-ffmpeg-headers=$(STAGING_DIR)/usr/include
|
||||||
|
|
||||||
|
define MOTION_INSTALL_TARGET_CMDS
|
||||||
|
cp $(@D)/motion $(TARGET_DIR)/usr/bin/motion
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(autotools-package))
|
||||||
|
|
2
package/motioneye/Config.in
Normal file
2
package/motioneye/Config.in
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
config BR2_PACKAGE_MOTIONEYE
|
||||||
|
bool "motioneye"
|
2
package/motioneye/dropbox.keys
Normal file
2
package/motioneye/dropbox.keys
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
CLIENT_ID="dwiw710jz6r60pq"
|
||||||
|
CLIENT_SECRET="8jz75qo405ritd5"
|
638
package/motioneye/extractl.py
Normal file
638
package/motioneye/extractl.py
Normal file
@ -0,0 +1,638 @@
|
|||||||
|
|
||||||
|
# Copyright (c) 2015 Calin Crisan
|
||||||
|
# This file is part of motionEyeOS.
|
||||||
|
#
|
||||||
|
# motionEyeOS 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os.path
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from config import additional_config
|
||||||
|
|
||||||
|
|
||||||
|
MOTIONEYE_CONF = '/data/etc/motioneye.conf'
|
||||||
|
OS_CONF = '/data/etc/os.conf'
|
||||||
|
HOSTNAME_CONF = '/data/etc/hostname'
|
||||||
|
DATE_CONF = '/data/etc/date.conf'
|
||||||
|
|
||||||
|
|
||||||
|
def _get_hostname():
|
||||||
|
try:
|
||||||
|
with open(HOSTNAME_CONF) as f:
|
||||||
|
hostname = f.read().strip()
|
||||||
|
logging.debug('hostname %s read from %s' % (hostname, HOSTNAME_CONF))
|
||||||
|
return hostname
|
||||||
|
|
||||||
|
except:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
def _set_hostname(hostname):
|
||||||
|
if hostname:
|
||||||
|
with open(HOSTNAME_CONF, 'w') as f:
|
||||||
|
f.write(hostname)
|
||||||
|
|
||||||
|
logging.debug('hostname %s written to %s' % (hostname, HOSTNAME_CONF))
|
||||||
|
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
os.remove(HOSTNAME_CONF)
|
||||||
|
logging.debug('hostname file %s removed' % HOSTNAME_CONF)
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _get_date_settings():
|
||||||
|
date_method = 'http'
|
||||||
|
date_host = 'google.com'
|
||||||
|
date_ntp_server = ''
|
||||||
|
date_timeout = 10
|
||||||
|
date_interval = 900
|
||||||
|
|
||||||
|
if os.path.exists(DATE_CONF):
|
||||||
|
logging.debug('reading date settings from %s' % DATE_CONF)
|
||||||
|
|
||||||
|
with open(DATE_CONF) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if line.startswith('#'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
name, value = line.split('=')
|
||||||
|
value = value.strip('"').strip("'")
|
||||||
|
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if name == 'date_method':
|
||||||
|
date_method = value
|
||||||
|
|
||||||
|
elif name == 'date_host':
|
||||||
|
date_host = value
|
||||||
|
|
||||||
|
elif name == 'date_ntp_server':
|
||||||
|
date_ntp_server = value
|
||||||
|
|
||||||
|
elif name == 'date_timeout':
|
||||||
|
date_timeout = int(value)
|
||||||
|
|
||||||
|
elif name == 'date_interval':
|
||||||
|
date_interval = int(value)
|
||||||
|
|
||||||
|
s = {
|
||||||
|
'dateMethod': date_method,
|
||||||
|
'dateHost': date_host,
|
||||||
|
'dateNtpServer': date_ntp_server,
|
||||||
|
'dateTimeout': date_timeout,
|
||||||
|
'dateInterval': date_interval
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.debug('date settings: method=%(dateMethod)s, host=%(dateHost)s, ntp_server=%(dateNtpServer)s, timeout=%(dateTimeout)s, interval=%(dateInterval)s' % s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def _set_date_settings(s):
|
||||||
|
s.setdefault('dateMethod', 'http')
|
||||||
|
s.setdefault('dateHost', 'google.com')
|
||||||
|
s.setdefault('dateNtpServer', '')
|
||||||
|
s.setdefault('dateTimeout', 10)
|
||||||
|
s.setdefault('dateInterval', 900)
|
||||||
|
|
||||||
|
logging.debug('writing date settings to %s: ' % DATE_CONF +
|
||||||
|
'method=%(dateMethod)s, host=%(dateHost)s, ntp_server=%(dateNtpServer)s, timeout=%(dateTimeout)s, interval=%(dateInterval)s' % s)
|
||||||
|
|
||||||
|
with open(DATE_CONF, 'w') as f:
|
||||||
|
f.write('date_method=%s\n' % s['dateMethod'])
|
||||||
|
f.write('date_host=%s\n' % s['dateHost'])
|
||||||
|
f.write('date_ntp_server=%s\n' % s['dateNtpServer'])
|
||||||
|
f.write('date_timeout=%s\n' % s['dateTimeout'])
|
||||||
|
f.write('date_interval=%s\n' % s['dateInterval'])
|
||||||
|
|
||||||
|
|
||||||
|
def _get_os_settings():
|
||||||
|
prereleases = False
|
||||||
|
|
||||||
|
if os.path.exists(OS_CONF):
|
||||||
|
logging.debug('reading OS settings from %s' % OS_CONF)
|
||||||
|
|
||||||
|
with open(OS_CONF) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if line.startswith('#'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
name, value = line.split('=')
|
||||||
|
value = value.strip('"').strip("'")
|
||||||
|
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if name == 'os_prereleases':
|
||||||
|
prereleases = value == 'true'
|
||||||
|
|
||||||
|
s = {
|
||||||
|
'prereleases': prereleases
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.debug('OS settings: prereleases=%(prereleases)s' % s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def _set_os_settings(s):
|
||||||
|
s = dict(s)
|
||||||
|
|
||||||
|
s.setdefault('prereleases', False)
|
||||||
|
|
||||||
|
logging.debug('writing OS settings to %s: ' % OS_CONF +
|
||||||
|
'prereleases=%(prereleases)s' % s)
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
if os.path.exists(OS_CONF):
|
||||||
|
with open(OS_CONF) as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
name, _ = line.split('=', 2)
|
||||||
|
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if name == 'os_prereleases':
|
||||||
|
lines[i] = 'os_prereleases="%s"' % str(s.pop('prereleases')).lower()
|
||||||
|
|
||||||
|
if 'prereleases' in s:
|
||||||
|
lines.append('os_prereleases="%s"' % str(s.pop('prereleases')).lower())
|
||||||
|
|
||||||
|
with open(OS_CONF, 'w') as f:
|
||||||
|
for line in lines:
|
||||||
|
if not line.strip():
|
||||||
|
continue
|
||||||
|
if not line.endswith('\n'):
|
||||||
|
line += '\n'
|
||||||
|
f.write(line)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_motioneye_settings():
|
||||||
|
port = 80
|
||||||
|
base_path = ''
|
||||||
|
motion_binary = '/usr/bin/motion'
|
||||||
|
debug = False
|
||||||
|
motion_keep_alive = False
|
||||||
|
|
||||||
|
if os.path.exists(MOTIONEYE_CONF):
|
||||||
|
logging.debug('reading motioneye settings from %s' % MOTIONEYE_CONF)
|
||||||
|
|
||||||
|
with open(MOTIONEYE_CONF) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
name, value = line.split(' ', 1)
|
||||||
|
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
name = name.replace('-', '_')
|
||||||
|
|
||||||
|
if name == 'port':
|
||||||
|
port = int(value)
|
||||||
|
|
||||||
|
elif name == 'base_path':
|
||||||
|
base_path = value.strip()
|
||||||
|
|
||||||
|
elif name == 'motion_binary':
|
||||||
|
motion_binary = value
|
||||||
|
|
||||||
|
elif name == 'log_level':
|
||||||
|
debug = value == 'debug'
|
||||||
|
|
||||||
|
elif name == 'mjpg_client_idle_timeout':
|
||||||
|
motion_keep_alive = value == '0'
|
||||||
|
|
||||||
|
s = {
|
||||||
|
'port': port,
|
||||||
|
'basePath': base_path,
|
||||||
|
'motionBinary': motion_binary,
|
||||||
|
'motionKeepAlive': motion_keep_alive,
|
||||||
|
'debug': debug
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.debug(('motioneye settings: port=%(port)s, base_path=%(basePath)s, motion_binary=%(motionBinary)s, ' +
|
||||||
|
'motion_keep_alive=%(motionKeepAlive)s, debug=%(debug)s') % s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def _set_motioneye_settings(s):
|
||||||
|
s = dict(s)
|
||||||
|
s.setdefault('port', 80)
|
||||||
|
s.setdefault('basePath', '')
|
||||||
|
s.setdefault('motionBinary', '/usr/bin/motion')
|
||||||
|
debug = s.setdefault('debug', False) # value needed later
|
||||||
|
s.setdefault('motion_keep_alive', False)
|
||||||
|
|
||||||
|
logging.debug('writing motioneye settings to %s: ' % MOTIONEYE_CONF +
|
||||||
|
('port=%(port)s, base_path=%(basePath)s, motion_binary=%(motionBinary)s, ' +
|
||||||
|
'motion_keep_alive=%(motionKeepAlive)s, debug=%(debug)s') % s)
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
if os.path.exists(MOTIONEYE_CONF):
|
||||||
|
with open(MOTIONEYE_CONF) as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
name, _ = line.split(' ', 2)
|
||||||
|
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
name = name.replace('-', '_')
|
||||||
|
|
||||||
|
if name == 'port':
|
||||||
|
lines[i] = 'port %s' % s.pop('port')
|
||||||
|
|
||||||
|
elif name == 'base_path':
|
||||||
|
base_path = s.pop('basePath')
|
||||||
|
if base_path:
|
||||||
|
lines[i] = 'base_path %s' % base_path
|
||||||
|
|
||||||
|
else:
|
||||||
|
lines[i] = None
|
||||||
|
|
||||||
|
elif name == 'motion_binary':
|
||||||
|
lines[i] = 'motion_binary %s' % s.pop('motionBinary')
|
||||||
|
|
||||||
|
elif name == 'log_level':
|
||||||
|
lines[i] = 'log_level %s' % ['info', 'debug'][s.pop('debug')]
|
||||||
|
|
||||||
|
elif name == 'mjpg_client_idle_timeout':
|
||||||
|
lines[i] = 'mjpg_client_idle_timeout %s' % [10, 0][s.pop('motionKeepAlive')]
|
||||||
|
|
||||||
|
lines = [l for l in lines if l is not None]
|
||||||
|
|
||||||
|
if 'port' in s:
|
||||||
|
lines.append('port %s' % s.pop('port'))
|
||||||
|
|
||||||
|
if s.get('basePath'):
|
||||||
|
lines.append('base_path %s' % s.pop('basePath'))
|
||||||
|
|
||||||
|
if 'motionBinary' in s:
|
||||||
|
lines.append('motion_binary %s' % s.pop('motionBinary'))
|
||||||
|
|
||||||
|
if 'debug' in s:
|
||||||
|
lines.append('log_level %s' % ['info', 'debug'][s.pop('debug')])
|
||||||
|
|
||||||
|
if 'motionKeepAlive' in s:
|
||||||
|
lines.append('mjpg_client_idle_timeout %s' % [10, 0][s.pop('motionKeepAlive')])
|
||||||
|
|
||||||
|
with open(MOTIONEYE_CONF, 'w') as f:
|
||||||
|
for line in lines:
|
||||||
|
if not line.strip():
|
||||||
|
continue
|
||||||
|
if not line.endswith('\n'):
|
||||||
|
line += '\n'
|
||||||
|
f.write(line)
|
||||||
|
|
||||||
|
# also update debug in os.conf
|
||||||
|
if debug:
|
||||||
|
cmd = "sed -i -r 's/os_debug=\"?false\"?/os_debug=\"true\"/' %s" % OS_CONF
|
||||||
|
|
||||||
|
else:
|
||||||
|
cmd = "sed -i -r 's/os_debug=\"?true\"?/os_debug=\"false\"/' %s" % OS_CONF
|
||||||
|
|
||||||
|
if os.system(cmd):
|
||||||
|
logging.error('failed to set debug flag in os.conf')
|
||||||
|
|
||||||
|
|
||||||
|
def _get_motion_log():
|
||||||
|
return '<a href="javascript:downloadFile(\'log/motion/\');">motion.log</a>'
|
||||||
|
|
||||||
|
|
||||||
|
def _get_motion_eye_log():
|
||||||
|
return '<a href="javascript:downloadFile(\'log/motioneye/\');">motioneye.log</a>'
|
||||||
|
|
||||||
|
|
||||||
|
def _get_messages_log():
|
||||||
|
return '<a href="javascript:downloadFile(\'log/messages/\');">messages.log</a>'
|
||||||
|
|
||||||
|
|
||||||
|
def _get_boot_log():
|
||||||
|
return '<a href="javascript:downloadFile(\'log/boot/\');">boot.log</a>'
|
||||||
|
|
||||||
|
|
||||||
|
def _get_dmesg_log():
|
||||||
|
return '<a href="javascript:downloadFile(\'log/dmesg/\');">dmesg.log</a>'
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def hostname():
|
||||||
|
return {
|
||||||
|
'label': 'Hostname',
|
||||||
|
'description': 'sets a custom hostname for the device (leave blank for default)',
|
||||||
|
'type': 'str',
|
||||||
|
'section': 'general',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': False,
|
||||||
|
'validate': '^[a-z0-9\-_.]{0,64}$',
|
||||||
|
'get': _get_hostname,
|
||||||
|
'set': _set_hostname
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def extraDateSeparator():
|
||||||
|
return {
|
||||||
|
'type': 'separator',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def dateMethod():
|
||||||
|
return {
|
||||||
|
'label': 'Date Method',
|
||||||
|
'description': 'decides whether NTP or HTTP is used for setting and updating the system date',
|
||||||
|
'type': 'choices',
|
||||||
|
'choices': [('http', 'HTTP'), ('ntp', 'NTP')],
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': True,
|
||||||
|
'get': _get_date_settings,
|
||||||
|
'set': _set_date_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def dateHost():
|
||||||
|
return {
|
||||||
|
'label': 'Date HTTP Host',
|
||||||
|
'description': 'sets the hostname or IP address to which the HTTP request will be made',
|
||||||
|
'type': 'str',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['dateMethod==http'],
|
||||||
|
'get': _get_date_settings,
|
||||||
|
'set': _set_date_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def dateNtpServer():
|
||||||
|
return {
|
||||||
|
'label': 'NTP Server',
|
||||||
|
'description': 'sets a custom NTP server (leave blank to use the default server)',
|
||||||
|
'type': 'str',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': False,
|
||||||
|
'depends': ['dateMethod==ntp'],
|
||||||
|
'get': _get_date_settings,
|
||||||
|
'set': _set_date_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def dateTimeout():
|
||||||
|
return {
|
||||||
|
'label': 'Date Updating Timeout',
|
||||||
|
'description': 'sets the number of seconds to wait when requesting the date/time',
|
||||||
|
'type': 'number',
|
||||||
|
'min': 1,
|
||||||
|
'max': 3600,
|
||||||
|
'unit': 's',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': True,
|
||||||
|
'get': _get_date_settings,
|
||||||
|
'set': _set_date_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def dateInterval():
|
||||||
|
return {
|
||||||
|
'label': 'Date Updating Interval',
|
||||||
|
'description': 'sets the interval between system date updates',
|
||||||
|
'type': 'number',
|
||||||
|
'min': 10,
|
||||||
|
'max': 86400,
|
||||||
|
'unit': 's',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['dateMethod==http'],
|
||||||
|
'get': _get_date_settings,
|
||||||
|
'set': _set_date_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def extraMotionEyeSeparator():
|
||||||
|
return {
|
||||||
|
'type': 'separator',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def port():
|
||||||
|
return {
|
||||||
|
'label': 'HTTP Port',
|
||||||
|
'description': 'sets the port on which the motionEye HTTP server listens',
|
||||||
|
'type': 'number',
|
||||||
|
'min': 1,
|
||||||
|
'max': 65535,
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': True,
|
||||||
|
'get': _get_motioneye_settings,
|
||||||
|
'set': _set_motioneye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def basePath():
|
||||||
|
return {
|
||||||
|
'label': 'Base Path',
|
||||||
|
'description': 'sets a base path of all the URIs used by motionEye (useful when running behind a reverse proxy exposing the motionEye UI at /cams, for example)',
|
||||||
|
'type': 'str',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_motioneye_settings,
|
||||||
|
'set': _set_motioneye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def motionBinary():
|
||||||
|
return {
|
||||||
|
'label': 'Motion Binary',
|
||||||
|
'description': 'sets the path to the motion binary',
|
||||||
|
'type': 'str',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': True,
|
||||||
|
'get': _get_motioneye_settings,
|
||||||
|
'set': _set_motioneye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def motionKeepAlive():
|
||||||
|
return {
|
||||||
|
'label': 'Motion Keep-alive',
|
||||||
|
'description': 'enables continuous motion daemon hang detection (at the expense of a slightly higher CPU usage)',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_motioneye_settings,
|
||||||
|
'set': _set_motioneye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def debug():
|
||||||
|
return {
|
||||||
|
'label': 'Enable Debugging',
|
||||||
|
'description': 'turning debugging on will generate verbose log messages and will mount all the partitions in read-write mode',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_motioneye_settings,
|
||||||
|
'set': _set_motioneye_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def prereleases():
|
||||||
|
return {
|
||||||
|
'label': 'Enable Prereleases',
|
||||||
|
'description': 'turning this option on will allow updating to prereleases (untested, possibly unstable versions)',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_os_settings,
|
||||||
|
'set': _set_os_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def extraLogsSeparator():
|
||||||
|
return {
|
||||||
|
'type': 'separator',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def motionLog():
|
||||||
|
return {
|
||||||
|
'label': 'Log Files',
|
||||||
|
'description': 'download the log files and include them with any issue you want to report',
|
||||||
|
'type': 'html',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'get': _get_motion_log,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def motionEyeLog():
|
||||||
|
return {
|
||||||
|
'type': 'html',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'get': _get_motion_eye_log,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def messagesLog():
|
||||||
|
return {
|
||||||
|
'type': 'html',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'get': _get_messages_log,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def bootLog():
|
||||||
|
return {
|
||||||
|
'type': 'html',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'get': _get_boot_log,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def dmesgLog():
|
||||||
|
return {
|
||||||
|
'type': 'html',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'get': _get_dmesg_log,
|
||||||
|
}
|
||||||
|
|
248
package/motioneye/ipctl.py
Normal file
248
package/motioneye/ipctl.py
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
|
||||||
|
# Copyright (c) 2015 Calin Crisan
|
||||||
|
# This file is part of motionEyeOS.
|
||||||
|
#
|
||||||
|
# motionEyeOS 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
|
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
from config import additional_config
|
||||||
|
|
||||||
|
|
||||||
|
STATIC_IP_CONF = '/data/etc/static_ip.conf'
|
||||||
|
|
||||||
|
|
||||||
|
def _get_ip_settings():
|
||||||
|
ip = None
|
||||||
|
ip_comment = False
|
||||||
|
cidr = '24'
|
||||||
|
gw = '192.168.1.1'
|
||||||
|
gw_comment = False
|
||||||
|
dns = '8.8.8.8'
|
||||||
|
dns_comment = False
|
||||||
|
|
||||||
|
if os.path.exists(STATIC_IP_CONF):
|
||||||
|
logging.debug('reading ip settings from %s' % STATIC_IP_CONF)
|
||||||
|
|
||||||
|
with open(STATIC_IP_CONF) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith('#'):
|
||||||
|
comment = True
|
||||||
|
line = line.strip('#')
|
||||||
|
|
||||||
|
else:
|
||||||
|
comment = False
|
||||||
|
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
match = re.match('^static_ip="(.*)/(.*)"$', line)
|
||||||
|
if match:
|
||||||
|
ip, cidr = match.groups()
|
||||||
|
ip_comment = comment
|
||||||
|
continue
|
||||||
|
|
||||||
|
match = re.match('^static_gw="(.*)"$', line)
|
||||||
|
if match:
|
||||||
|
gw = match.group(1)
|
||||||
|
gw_comment = comment
|
||||||
|
continue
|
||||||
|
|
||||||
|
match = re.match('^static_dns="(.*)"$', line)
|
||||||
|
if match:
|
||||||
|
dns = match.group(1)
|
||||||
|
dns_comment = comment
|
||||||
|
continue
|
||||||
|
|
||||||
|
if ip is None or ip_comment:
|
||||||
|
type = 'dhcp'
|
||||||
|
|
||||||
|
else:
|
||||||
|
type = 'static'
|
||||||
|
|
||||||
|
if ip is None:
|
||||||
|
ip = '192.168.1.101'
|
||||||
|
|
||||||
|
bits = 0
|
||||||
|
for i in xrange(32 - int(cidr), 32):
|
||||||
|
bits |= (1 << i)
|
||||||
|
|
||||||
|
mask = '%d.%d.%d.%d' % ((bits & 0xff000000) >> 24, (bits & 0xff0000) >> 16, (bits & 0xff00) >> 8 , (bits & 0xff))
|
||||||
|
|
||||||
|
if gw_comment and type == 'static':
|
||||||
|
gw = None
|
||||||
|
|
||||||
|
if dns_comment and type == 'static':
|
||||||
|
dns = None
|
||||||
|
|
||||||
|
s = {
|
||||||
|
'ipConfigType': type,
|
||||||
|
'ipConfigStaticAddr': ip,
|
||||||
|
'ipConfigStaticMask': mask,
|
||||||
|
'ipConfigStaticGw': gw,
|
||||||
|
'ipConfigStaticDns': dns
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.debug(('ip settings: type=%(ipConfigType)s, addr=%(ipConfigStaticAddr)s, mask=%(ipConfigStaticMask)s, ' +
|
||||||
|
'gw=%(ipConfigStaticGw)s, dns=%(ipConfigStaticDns)s') % s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def _set_ip_settings(s):
|
||||||
|
type = s.get('ipConfigType', 'dhcp')
|
||||||
|
ip = s.get('ipConfigStaticAddr', '192.168.1.101')
|
||||||
|
mask = s.get('ipConfigStaticMask', '255.255.255.0')
|
||||||
|
gw = s.get('ipConfigStaticGw', '192.168.1.1')
|
||||||
|
dns = s.get('ipConfigStaticDns', '8.8.8.8')
|
||||||
|
|
||||||
|
logging.debug('writing ip settings to %s: ' % STATIC_IP_CONF +
|
||||||
|
('type=%(ipConfigType)s, addr=%(ipConfigStaticAddr)s, mask=%(ipConfigStaticMask)s, ' +
|
||||||
|
'gw=%(ipConfigStaticGw)s, dns=%(ipConfigStaticDns)s') % s)
|
||||||
|
|
||||||
|
cidr = '24'
|
||||||
|
if mask:
|
||||||
|
binary_str = ''
|
||||||
|
for octet in mask.split('.'):
|
||||||
|
binary_str += bin(int(octet))[2:].zfill(8)
|
||||||
|
cidr = str(len(binary_str.rstrip('0')))
|
||||||
|
|
||||||
|
current_settings = OrderedDict()
|
||||||
|
if os.path.exists(STATIC_IP_CONF):
|
||||||
|
with open(STATIC_IP_CONF, 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip().split('=', 1)
|
||||||
|
if len(line) != 2:
|
||||||
|
continue
|
||||||
|
key, value = line
|
||||||
|
if key.startswith('#'):
|
||||||
|
current_settings[key.strip('#')] = (value, False)
|
||||||
|
|
||||||
|
else:
|
||||||
|
current_settings[key] = (value, True)
|
||||||
|
|
||||||
|
enabled = type != 'dhcp'
|
||||||
|
current_settings['static_ip'] = ('"%s/%s"' % (ip, cidr), enabled)
|
||||||
|
current_settings['static_gw'] = ('"%s"' % gw, enabled)
|
||||||
|
current_settings['static_dns'] = ('"%s"' % dns, enabled)
|
||||||
|
|
||||||
|
with open(STATIC_IP_CONF, 'w') as f:
|
||||||
|
for key, value in current_settings.items():
|
||||||
|
(value, enabled) = value
|
||||||
|
if not enabled:
|
||||||
|
key = '#' + key
|
||||||
|
f.write('%s=%s\n' % (key, value))
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def ipSeparator():
|
||||||
|
return {
|
||||||
|
'type': 'separator',
|
||||||
|
'section': 'network',
|
||||||
|
'advanced': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def ipConfigType():
|
||||||
|
return {
|
||||||
|
'label': 'IP Configuration',
|
||||||
|
'description': 'select the way your IP address is configured',
|
||||||
|
'type': 'choices',
|
||||||
|
'choices': [('dhcp', 'Automatic (DHCP)'), ('static', 'Manual (Static IP)')],
|
||||||
|
'section': 'network',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_ip_settings,
|
||||||
|
'set': _set_ip_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def ipConfigStaticAddr():
|
||||||
|
return {
|
||||||
|
'label': 'IP Address',
|
||||||
|
'description': 'manually set your static IP address',
|
||||||
|
'type': 'str',
|
||||||
|
'validate': '^[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?$',
|
||||||
|
'section': 'network',
|
||||||
|
'advanced': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['ipConfigType==static'],
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_ip_settings,
|
||||||
|
'set': _set_ip_settings,
|
||||||
|
'get_set_dict': True,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def ipConfigStaticMask():
|
||||||
|
return {
|
||||||
|
'label': 'Network Mask',
|
||||||
|
'description': 'manually set your network mask',
|
||||||
|
'type': 'str',
|
||||||
|
'validate': '^[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?$',
|
||||||
|
'section': 'network',
|
||||||
|
'advanced': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['ipConfigType==static'],
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_ip_settings,
|
||||||
|
'set': _set_ip_settings,
|
||||||
|
'get_set_dict': True,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def ipConfigStaticGw():
|
||||||
|
return {
|
||||||
|
'label': 'Default Gateway',
|
||||||
|
'description': 'manually set your default gateway',
|
||||||
|
'type': 'str',
|
||||||
|
'validate': '^[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?$',
|
||||||
|
'section': 'network',
|
||||||
|
'advanced': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['ipConfigType==static'],
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_ip_settings,
|
||||||
|
'set': _set_ip_settings,
|
||||||
|
'get_set_dict': True,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def ipConfigStaticDns():
|
||||||
|
return {
|
||||||
|
'label': 'DNS Server',
|
||||||
|
'description': 'manually set your DNS server',
|
||||||
|
'type': 'str',
|
||||||
|
'validate': '^[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?$',
|
||||||
|
'section': 'network',
|
||||||
|
'advanced': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['ipConfigType==static'],
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_ip_settings,
|
||||||
|
'set': _set_ip_settings,
|
||||||
|
'get_set_dict': True,
|
||||||
|
}
|
||||||
|
|
71
package/motioneye/motioneye.mk
Normal file
71
package/motioneye/motioneye.mk
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#############################################################
|
||||||
|
#
|
||||||
|
# motioneye
|
||||||
|
#
|
||||||
|
#############################################################
|
||||||
|
|
||||||
|
MOTIONEYE_VERSION = 0f92e7bd26a79f1c0d55b4d0ce17c3d434496c10
|
||||||
|
MOTIONEYE_SITE = $(call github,ccrisan,motioneye,$(MOTIONEYE_VERSION))
|
||||||
|
MOTIONEYE_SOURCE = $(MOTIONEYE_VERSION).tar.gz
|
||||||
|
MOTIONEYE_LICENSE = GPLv3
|
||||||
|
MOTIONEYE_LICENSE_FILES = LICENCE
|
||||||
|
MOTIONEYE_INSTALL_TARGET = YES
|
||||||
|
MOTIONEYE_SETUP_TYPE = setuptools
|
||||||
|
|
||||||
|
DST_DIR = $(TARGET_DIR)/usr/lib/python2.7/site-packages/motioneye
|
||||||
|
SHARE_DIR = $(TARGET_DIR)/usr/share/motioneye
|
||||||
|
BOARD = $(shell basename $(BASE_DIR))
|
||||||
|
BOARD_DIR = $(BASE_DIR)/../../board/$(BOARD)
|
||||||
|
COMMON_DIR = $(BASE_DIR)/../../board/common
|
||||||
|
|
||||||
|
|
||||||
|
define MOTIONEYE_INSTALL_TARGET_CMDS
|
||||||
|
# setuptools install
|
||||||
|
(cd $($(PKG)_BUILDDIR)/; \
|
||||||
|
$($(PKG)_BASE_ENV) $($(PKG)_ENV) \
|
||||||
|
$($(PKG)_PYTHON_INTERPRETER) setup.py install \
|
||||||
|
$($(PKG)_BASE_INSTALL_TARGET_OPTS) \
|
||||||
|
$($(PKG)_INSTALL_TARGET_OPTS))
|
||||||
|
|
||||||
|
# additional config modules
|
||||||
|
cp package/motioneye/update.py $(DST_DIR)
|
||||||
|
cp package/motioneye/ipctl.py $(DST_DIR)
|
||||||
|
cp package/motioneye/servicectl.py $(DST_DIR)
|
||||||
|
cp package/motioneye/watchctl.py $(DST_DIR)
|
||||||
|
cp package/motioneye/extractl.py $(DST_DIR)
|
||||||
|
test -d $(BOARD_DIR)/motioneye-modules && cp $(BOARD_DIR)/motioneye-modules/*.py $(DST_DIR) || true
|
||||||
|
grep servicectl $(DST_DIR)/config.py &>/dev/null || echo -e '\nimport ipctl\nimport servicectl\nimport watchctl\nimport extractl\ntry:\n import boardctl\nexcept ImportError:\n pass' >> $(DST_DIR)/config.py
|
||||||
|
|
||||||
|
# log files
|
||||||
|
if ! grep 'motioneye.log' $(DST_DIR)/handlers.py &>/dev/null; then \
|
||||||
|
lineno=$$(grep -n -m1 LOGS $(DST_DIR)/handlers.py | cut -d ':' -f 1); \
|
||||||
|
head -n $$(($$lineno + 1)) $(DST_DIR)/handlers.py > /tmp/handlers.py.new; \
|
||||||
|
echo " 'motioneye': ('/var/log/motioneye.log', 'motioneye.log')," >> /tmp/handlers.py.new; \
|
||||||
|
echo " 'messages': ('/var/log/messages', 'messages.log')," >> /tmp/handlers.py.new; \
|
||||||
|
echo " 'boot': ('/var/log/boot.log', 'boot.log')," >> /tmp/handlers.py.new; \
|
||||||
|
echo " 'dmesg': ('/var/log/dmesg.log', 'dmesg.log')," >> /tmp/handlers.py.new; \
|
||||||
|
tail -n +$$(($$lineno + 2)) $(DST_DIR)/handlers.py >> /tmp/handlers.py.new; \
|
||||||
|
mv /tmp/handlers.py.new $(DST_DIR)/handlers.py; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# version & update
|
||||||
|
source $(COMMON_DIR)/overlay/etc/version; \
|
||||||
|
sed -r -i "s%VERSION = .*%VERSION = '$$os_version'%" $(DST_DIR)/__init__.py
|
||||||
|
sed -r -i "s%enable_update=False%enable_update=True%" $(DST_DIR)/handlers.py
|
||||||
|
source package/motioneye/dropbox.keys; \
|
||||||
|
sed -i "s/dropbox_client_id_placeholder/$$CLIENT_ID/" $(DST_DIR)/uploadservices.py; \
|
||||||
|
sed -i "s/dropbox_client_secret_placeholder/$$CLIENT_SECRET/" $(DST_DIR)/uploadservices.py
|
||||||
|
|
||||||
|
# (re)compile all python modules
|
||||||
|
$($(PKG)_PYTHON_INTERPRETER) -m compileall -d /usr/lib/python2.7/site-packages/motioneye -f $(DST_DIR)
|
||||||
|
|
||||||
|
# meyectl
|
||||||
|
echo -e '#!/bin/bash\n/usr/bin/python /usr/lib/python2.7/site-packages/motioneye/meyectl.pyc "$$@"' > $(TARGET_DIR)/usr/bin/meyectl
|
||||||
|
chmod +x $(TARGET_DIR)/usr/bin/meyectl
|
||||||
|
|
||||||
|
# cleanups
|
||||||
|
rm -rf $(SHARE_DIR)/extra
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(python-package))
|
||||||
|
|
314
package/motioneye/servicectl.py
Normal file
314
package/motioneye/servicectl.py
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
|
||||||
|
# Copyright (c) 2015 Calin Crisan
|
||||||
|
# This file is part of motionEyeOS.
|
||||||
|
#
|
||||||
|
# motionEyeOS 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
|
|
||||||
|
from config import additional_config, additional_section
|
||||||
|
|
||||||
|
|
||||||
|
FTP_CONF = '/data/etc/proftpd.conf'
|
||||||
|
FTP_DISABLE_FILE = '/data/etc/no_S61proftpd'
|
||||||
|
SMB_CONF = '/data/etc/smb.conf'
|
||||||
|
SMB_DISABLE_FILE = '/data/etc/no_S62smb'
|
||||||
|
SSH_DISABLE_FILE = '/data/etc/no_S60sshd'
|
||||||
|
|
||||||
|
|
||||||
|
def _get_service_settings():
|
||||||
|
ftp_enabled = True
|
||||||
|
ftp_auth = True
|
||||||
|
ftp_writable = False
|
||||||
|
smb_enabled = True
|
||||||
|
smb_auth = True
|
||||||
|
smb_writable = False
|
||||||
|
ssh_enabled = True
|
||||||
|
|
||||||
|
# FTP
|
||||||
|
if os.path.exists(FTP_DISABLE_FILE):
|
||||||
|
ftp_enabled = False
|
||||||
|
|
||||||
|
if os.path.exists(FTP_CONF):
|
||||||
|
logging.debug('reading ftp settings from %s' % FTP_CONF)
|
||||||
|
|
||||||
|
with open(FTP_CONF) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith('#'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if line == '<Anonymous ~ftp>':
|
||||||
|
ftp_auth = False
|
||||||
|
|
||||||
|
elif line == 'AllowAll':
|
||||||
|
ftp_writable = True
|
||||||
|
|
||||||
|
# SMB
|
||||||
|
if os.path.exists(SMB_DISABLE_FILE):
|
||||||
|
smb_enabled = False
|
||||||
|
|
||||||
|
if os.path.exists(SMB_CONF):
|
||||||
|
logging.debug('reading smb settings from %s' % SMB_CONF)
|
||||||
|
|
||||||
|
with open(SMB_CONF) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if re.match('^\s*public\s*=\s*yes\s*$', line):
|
||||||
|
smb_auth = False
|
||||||
|
|
||||||
|
elif re.match('^\s*writable\s*=\s*yes\s*$', line):
|
||||||
|
smb_writable = True
|
||||||
|
|
||||||
|
# SSH
|
||||||
|
if os.path.exists(SSH_DISABLE_FILE):
|
||||||
|
ssh_enabled = False
|
||||||
|
|
||||||
|
s = {
|
||||||
|
'ftpEnabled': ftp_enabled,
|
||||||
|
'ftpAuth': ftp_auth,
|
||||||
|
'ftpWritable': ftp_writable,
|
||||||
|
'smbEnabled': smb_enabled,
|
||||||
|
'smbAuth': smb_auth,
|
||||||
|
'smbWritable': smb_writable,
|
||||||
|
'sshEnabled': ssh_enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.debug(('service settings: ftp=%(ftpEnabled)s, ftp_auth=%(ftpAuth)s, ftp_writable=%(ftpWritable)s, ' +
|
||||||
|
'smb=%(smbEnabled)s, smb_auth=%(smbAuth)s, smb_writable=%(smbWritable)s, ' +
|
||||||
|
'ssh=%(sshEnabled)s') % s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def _set_service_settings(s):
|
||||||
|
s.setdefault('ftpEnabled', True)
|
||||||
|
s.setdefault('ftpAuth', True)
|
||||||
|
s.setdefault('ftpWritable', False)
|
||||||
|
s.setdefault('smbEnabled', True)
|
||||||
|
s.setdefault('smbAuth', True)
|
||||||
|
s.setdefault('smbWritable', False)
|
||||||
|
s.setdefault('sshEnabled', True)
|
||||||
|
|
||||||
|
logging.debug(('saving service settings: ftp=%(ftpEnabled)s, ftp_auth=%(ftpAuth)s, ftp_writable=%(ftpWritable)s, ' +
|
||||||
|
'smb=%(smbEnabled)s, smb_auth=%(smbAuth)s, smb_writable=%(smbWritable)s, ' +
|
||||||
|
'ssh=%(sshEnabled)s') % s)
|
||||||
|
|
||||||
|
# FTP
|
||||||
|
ftp_mode = 'off' if not s['ftpEnabled'] else ('public' if not s['ftpAuth'] else ('auth' if not s['ftpWritable'] else 'writable'))
|
||||||
|
logging.debug('setting FTP mode: %s' % ftp_mode)
|
||||||
|
if s['ftpEnabled']:
|
||||||
|
try:
|
||||||
|
os.remove(FTP_DISABLE_FILE)
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
with open(FTP_DISABLE_FILE, 'w'):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with open(FTP_CONF, 'w') as f:
|
||||||
|
if s['ftpAuth']:
|
||||||
|
if s['ftpWritable']:
|
||||||
|
f.write('<Limit WRITE>\n')
|
||||||
|
f.write(' AllowAll\n')
|
||||||
|
f.write('</Limit>\n')
|
||||||
|
|
||||||
|
else:
|
||||||
|
f.write('<Anonymous ~ftp>\n')
|
||||||
|
f.write(' User ftp\n')
|
||||||
|
f.write(' Group nogroup\n')
|
||||||
|
f.write(' UserAlias anonymous ftp\n')
|
||||||
|
f.write(' MaxClients 4\n')
|
||||||
|
f.write(' <Limit WRITE>\n')
|
||||||
|
f.write(' DenyAll\n')
|
||||||
|
f.write(' </Limit>\n')
|
||||||
|
f.write('</Anonymous>\n')
|
||||||
|
|
||||||
|
# SMB
|
||||||
|
smb_mode = 'off' if not s['smbEnabled'] else ('public' if not s['smbAuth'] else ('auth' if not s['smbWritable'] else 'writable'))
|
||||||
|
logging.debug('setting SMB mode: %s' % smb_mode)
|
||||||
|
if s['smbEnabled']:
|
||||||
|
try:
|
||||||
|
os.remove(SMB_DISABLE_FILE)
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
with open(SMB_DISABLE_FILE, 'w'):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with open(SMB_CONF, 'w') as f:
|
||||||
|
if s['smbAuth']:
|
||||||
|
if s['smbWritable']:
|
||||||
|
f.write('writable = yes\n')
|
||||||
|
f.write('public = no\n')
|
||||||
|
|
||||||
|
else:
|
||||||
|
f.write('writable = no\n')
|
||||||
|
f.write('public = yes\n')
|
||||||
|
|
||||||
|
# SSH
|
||||||
|
ssh_mode = 'off' if not s['sshEnabled'] else 'enabled'
|
||||||
|
logging.debug('setting SSH mode: %s' % ssh_mode)
|
||||||
|
if s['sshEnabled']:
|
||||||
|
try:
|
||||||
|
os.remove(SSH_DISABLE_FILE)
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
with open(SSH_DISABLE_FILE, 'w'):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@additional_section
|
||||||
|
def services():
|
||||||
|
return {
|
||||||
|
'label': 'Services',
|
||||||
|
'description': 'configure extra services (such as FTP or SSH)',
|
||||||
|
'advanced': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def ftpEnabled():
|
||||||
|
return {
|
||||||
|
'label': 'Enable FTP Server',
|
||||||
|
'description': 'enable this if you want to access the files on your motionEyeOS system using FTP',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'services',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_service_settings,
|
||||||
|
'set': _set_service_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def ftpAuth():
|
||||||
|
return {
|
||||||
|
'label': 'Require FTP Authentication',
|
||||||
|
'description': 'enable this if you want the FTP server to ask for credentials (i.e. to disable anonymous logins)',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'services',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'depends': ['ftpEnabled'],
|
||||||
|
'get': _get_service_settings,
|
||||||
|
'set': _set_service_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def ftpWritable():
|
||||||
|
return {
|
||||||
|
'label': 'Enable FTP Write Support',
|
||||||
|
'description': 'enable this if you want to allow creating, editing or removing files/directories through FTP (i.e. to disable read-only mode)',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'services',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'depends': ['ftpAuth', 'ftpEnabled'],
|
||||||
|
'get': _get_service_settings,
|
||||||
|
'set': _set_service_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def ftpSeparator():
|
||||||
|
return {
|
||||||
|
'type': 'separator',
|
||||||
|
'section': 'services',
|
||||||
|
'advanced': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def smbEnabled():
|
||||||
|
return {
|
||||||
|
'label': 'Enable Samba Server',
|
||||||
|
'description': 'enable this if you want files on your motionEyeOS system to be visible on the local network (using SMB protocol)',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'services',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_service_settings,
|
||||||
|
'set': _set_service_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def smbAuth():
|
||||||
|
return {
|
||||||
|
'label': 'Require Samba Authentication',
|
||||||
|
'description': 'enable this if you want the Samba server to ask for credentials (i.e. to disable guest access)',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'services',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'depends': ['smbEnabled'],
|
||||||
|
'get': _get_service_settings,
|
||||||
|
'set': _set_service_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def smbWritable():
|
||||||
|
return {
|
||||||
|
'label': 'Enable Samba Write Support',
|
||||||
|
'description': 'enable this if you want to allow creating, editing or removing files/directories on your motionEyeOS system from the local network',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'services',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'depends': ['smbAuth', 'smbEnabled'],
|
||||||
|
'get': _get_service_settings,
|
||||||
|
'set': _set_service_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def smbSeparator():
|
||||||
|
return {
|
||||||
|
'type': 'separator',
|
||||||
|
'section': 'services',
|
||||||
|
'advanced': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def sshEnabled():
|
||||||
|
return {
|
||||||
|
'label': 'Enable SSH Server',
|
||||||
|
'description': 'enable this if you want to login remotely on your motionEyeOS system using an SSH client (such as Putty)',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'services',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_service_settings,
|
||||||
|
'set': _set_service_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
263
package/motioneye/update.py
Normal file
263
package/motioneye/update.py
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
|
||||||
|
# Copyright (c) 2015 Calin Crisan
|
||||||
|
# This file is part of motionEyeOS.
|
||||||
|
#
|
||||||
|
# motionEyeOS 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import ssl
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
import urllib2
|
||||||
|
|
||||||
|
import settings
|
||||||
|
|
||||||
|
|
||||||
|
_BOARD = open('/etc/board').read().strip()
|
||||||
|
_REPO = ('ccrisan', 'motioneyeos')
|
||||||
|
_DOWNLOAD_URL = 'https://github.com/{owner}/{repo}/releases/download/%(version)s/motioneyeos-%(board)s-%(version)s.img.gz'.format(
|
||||||
|
owner=_REPO[0], repo=_REPO[1])
|
||||||
|
_LIST_VERSIONS_URL = 'https://api.github.com/repos/{owner}/{repo}/releases'.format(
|
||||||
|
owner=_REPO[0], repo=_REPO[1])
|
||||||
|
_DOWNLOAD_DIR = '/data/.firmware_update'
|
||||||
|
_DOWNLOAD_FILE_NAME = os.path.join(_DOWNLOAD_DIR, 'firmware.gz')
|
||||||
|
|
||||||
|
|
||||||
|
# versions
|
||||||
|
|
||||||
|
def get_version():
|
||||||
|
import motioneye
|
||||||
|
|
||||||
|
return motioneye.VERSION
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_versions():
|
||||||
|
url = _LIST_VERSIONS_URL
|
||||||
|
url += '?_=' + str(int(time.time())) # prevents caching
|
||||||
|
|
||||||
|
want_prereleases = subprocess.check_output('source /data/etc/os.conf && echo $os_prereleases', shell=True, stderr=subprocess.STDOUT).strip() == 'true'
|
||||||
|
|
||||||
|
try:
|
||||||
|
logging.debug('board is %s' % _BOARD)
|
||||||
|
logging.debug('fetching %s...' % url)
|
||||||
|
|
||||||
|
context = ssl._create_unverified_context()
|
||||||
|
|
||||||
|
response = urllib2.urlopen(url, timeout=settings.REMOTE_REQUEST_TIMEOUT, context=context)
|
||||||
|
releases = json.load(response)
|
||||||
|
|
||||||
|
versions = []
|
||||||
|
for release in releases:
|
||||||
|
if release.get('prerelease') and not want_prereleases:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for asset in release.get('assets', []):
|
||||||
|
if not re.match('^motioneyeos-%s-\d{8}\.img.gz$' % _BOARD, asset['name']):
|
||||||
|
continue
|
||||||
|
|
||||||
|
versions.append(release['name'])
|
||||||
|
|
||||||
|
logging.debug('available versions: %(versions)s' % {'versions': ', '.join(versions)})
|
||||||
|
|
||||||
|
return sorted(versions)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error('could not get versions: %s' % e, exc_info=True)
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def compare_versions(version1, version2):
|
||||||
|
version1 = re.sub('[^0-9.]', '', version1)
|
||||||
|
version2 = re.sub('[^0-9.]', '', version2)
|
||||||
|
|
||||||
|
def int_or_0(n):
|
||||||
|
try:
|
||||||
|
return int(n)
|
||||||
|
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
version1 = [int_or_0(n) for n in version1.split('.')]
|
||||||
|
version2 = [int_or_0(n) for n in version2.split('.')]
|
||||||
|
|
||||||
|
len1 = len(version1)
|
||||||
|
len2 = len(version2)
|
||||||
|
length = min(len1, len2)
|
||||||
|
for i in xrange(length):
|
||||||
|
p1 = version1[i]
|
||||||
|
p2 = version2[i]
|
||||||
|
|
||||||
|
if p1 < p2:
|
||||||
|
return -1
|
||||||
|
|
||||||
|
elif p1 > p2:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if len1 < len2:
|
||||||
|
return -1
|
||||||
|
|
||||||
|
elif len1 > len2:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
# updating
|
||||||
|
|
||||||
|
def download(version):
|
||||||
|
url = _DOWNLOAD_URL % {'version': version, 'board': _BOARD}
|
||||||
|
|
||||||
|
try:
|
||||||
|
logging.info('downloading %s...' % url)
|
||||||
|
|
||||||
|
shutil.rmtree(_DOWNLOAD_DIR, ignore_errors=True)
|
||||||
|
os.makedirs(_DOWNLOAD_DIR)
|
||||||
|
subprocess.check_call(['/usr/bin/wget', url, '--no-check-certificate', '-O', _DOWNLOAD_FILE_NAME])
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error('could not download update: %s' % e)
|
||||||
|
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
logging.info('decompressing %s...' % _DOWNLOAD_FILE_NAME)
|
||||||
|
|
||||||
|
subprocess.check_call(['/bin/gunzip', _DOWNLOAD_FILE_NAME])
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error('could not decompress archive: %s' % e)
|
||||||
|
|
||||||
|
raise
|
||||||
|
|
||||||
|
extracted_file_name = _DOWNLOAD_FILE_NAME.replace('.gz', '')
|
||||||
|
|
||||||
|
try:
|
||||||
|
logging.info('reading partiton table...')
|
||||||
|
|
||||||
|
output = subprocess.check_output(['/sbin/fdisk', '-l', extracted_file_name])
|
||||||
|
lines = [l.strip().replace('*', ' ') for l in output.split('\n') if l.startswith(extracted_file_name)]
|
||||||
|
boot_info = lines[0].split()
|
||||||
|
root_info = lines[1].split()
|
||||||
|
|
||||||
|
boot_start, boot_end = int(boot_info[1]), int(boot_info[2])
|
||||||
|
root_start, root_end = int(root_info[1]), int(root_info[2])
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error('could not read partition table: %s' % e)
|
||||||
|
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
logging.info('extracting boot.img...')
|
||||||
|
|
||||||
|
subprocess.check_call(['/bin/dd', 'if=' + extracted_file_name, 'of=' + os.path.join(_DOWNLOAD_DIR, 'boot.img'),
|
||||||
|
'bs=2048', 'skip=' + str(boot_start / 4), 'count=' + str((boot_end - boot_start + 1) / 4)])
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error('could not extract boot.img: %s' % e)
|
||||||
|
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
logging.info('extracting root.img...')
|
||||||
|
|
||||||
|
subprocess.check_call(['/bin/dd', 'if=' + extracted_file_name, 'of=' + os.path.join(_DOWNLOAD_DIR, 'root.img'),
|
||||||
|
'bs=2048', 'skip=' + str(root_start / 4), 'count=' + str((root_end - root_start + 1) / 4)])
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error('could not extract root.img: %s' % e)
|
||||||
|
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def perform_update(version):
|
||||||
|
logging.info('updating to version %(version)s...' % {'version': version})
|
||||||
|
|
||||||
|
logging.info('killing motioneye init script...')
|
||||||
|
os.system('kill $(pidof S85motioneye)')
|
||||||
|
|
||||||
|
logging.info('stopping netwatch init script...')
|
||||||
|
os.system('/etc/init.d/S41netwatch stop')
|
||||||
|
|
||||||
|
download(version)
|
||||||
|
|
||||||
|
logging.info('backing up /boot/config.txt')
|
||||||
|
if os.system('/bin/cp /boot/config.txt /tmp/config.txt'):
|
||||||
|
logging.error('failed to backup /boot/config.txt')
|
||||||
|
|
||||||
|
raise Exception('failed to backup /boot/config.txt')
|
||||||
|
|
||||||
|
logging.info('unmounting boot partition...')
|
||||||
|
if os.system('/bin/umount /boot'):
|
||||||
|
logging.error('failed to unmount boot partition')
|
||||||
|
|
||||||
|
raise Exception('failed to unmount boot partition')
|
||||||
|
|
||||||
|
try:
|
||||||
|
logging.info('installing boot image...')
|
||||||
|
boot_img = os.path.join(_DOWNLOAD_DIR, 'boot.img')
|
||||||
|
|
||||||
|
subprocess.check_call(['/bin/dd', 'if=' + boot_img, 'of=/dev/mmcblk0p1', 'bs=1M'])
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error('could not install boot image: %s' % e)
|
||||||
|
|
||||||
|
raise
|
||||||
|
|
||||||
|
logging.info('mounting boot partition read-write...')
|
||||||
|
if os.system('/bin/mount -o rw /dev/mmcblk0p1 /boot'):
|
||||||
|
logging.error('failed to mount boot partition')
|
||||||
|
|
||||||
|
raise Exception('failed to mount boot partition')
|
||||||
|
|
||||||
|
logging.info('restoring up /boot/config.txt')
|
||||||
|
if os.system('/bin/cp /tmp/config.txt /boot/config.txt'):
|
||||||
|
logging.error('failed to restore /boot/config.txt')
|
||||||
|
|
||||||
|
raise Exception('failed to restore /boot/config.txt')
|
||||||
|
|
||||||
|
logging.info('preparing to boot in fwupdate mode...')
|
||||||
|
try:
|
||||||
|
config_lines = [c.strip() for c in open('/boot/config.txt', 'r').readlines() if c.strip()]
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error('failed to read /boot/config.txt: %s' % e, exc_info=True)
|
||||||
|
|
||||||
|
raise
|
||||||
|
|
||||||
|
config_lines.append('initramfs fwupdater.gz')
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open('/boot/config.txt', 'w') as f:
|
||||||
|
for line in config_lines:
|
||||||
|
f.write(line + '\n')
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error('failed to write /boot/config.txt: %s' % e, exc_info=True)
|
||||||
|
|
||||||
|
raise
|
||||||
|
|
||||||
|
logging.info('rebooting...')
|
||||||
|
|
||||||
|
if os.system('/sbin/reboot'):
|
||||||
|
logging.error('failed to reboot')
|
||||||
|
logging.info('hard rebooting...')
|
||||||
|
open('/proc/sysrq-trigger', 'w').write('b') # reboot
|
||||||
|
|
282
package/motioneye/watchctl.py
Normal file
282
package/motioneye/watchctl.py
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
|
||||||
|
# Copyright (c) 2015 Calin Crisan
|
||||||
|
# This file is part of motionEyeOS.
|
||||||
|
#
|
||||||
|
# motionEyeOS 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
from config import additional_config, additional_section
|
||||||
|
|
||||||
|
|
||||||
|
WATCH_CONF = '/data/etc/watch.conf'
|
||||||
|
|
||||||
|
|
||||||
|
def _get_watch_settings():
|
||||||
|
watch_link = False
|
||||||
|
watch_link_timeout = 20
|
||||||
|
|
||||||
|
watch_connect = False
|
||||||
|
watch_connect_host = 'www.google.com'
|
||||||
|
watch_connect_port = 80
|
||||||
|
watch_connect_retries = 3
|
||||||
|
watch_connect_timeout = 5
|
||||||
|
watch_connect_interval = 20
|
||||||
|
|
||||||
|
if os.path.exists(WATCH_CONF):
|
||||||
|
logging.debug('reading watch settings from %s' % WATCH_CONF)
|
||||||
|
|
||||||
|
with open(WATCH_CONF) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
comment = False
|
||||||
|
if line.startswith('#'):
|
||||||
|
line = line.strip('#')
|
||||||
|
comment = True
|
||||||
|
|
||||||
|
try:
|
||||||
|
name, value = line.split('=')
|
||||||
|
value = value.strip('"').strip("'")
|
||||||
|
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if name == 'link_watch':
|
||||||
|
watch_link = (value == 'true') and not comment
|
||||||
|
|
||||||
|
elif name == 'link_watch_timeout':
|
||||||
|
watch_link_timeout = int(value)
|
||||||
|
|
||||||
|
elif name == 'netwatch_host':
|
||||||
|
watch_connect = not comment
|
||||||
|
watch_connect_host = value
|
||||||
|
|
||||||
|
elif name == 'netwatch_port':
|
||||||
|
watch_connect_port = int(value)
|
||||||
|
|
||||||
|
elif name == 'netwatch_timeout':
|
||||||
|
watch_connect_timeout = int(value)
|
||||||
|
|
||||||
|
elif name == 'netwatch_retries':
|
||||||
|
watch_connect_retries = int(value)
|
||||||
|
|
||||||
|
elif name == 'netwatch_interval':
|
||||||
|
watch_connect_interval = int(value)
|
||||||
|
|
||||||
|
s = {
|
||||||
|
'watchLink': watch_link,
|
||||||
|
'watchLinkTimeout': watch_link_timeout,
|
||||||
|
'watchConnect': watch_connect,
|
||||||
|
'watchConnectHost': watch_connect_host,
|
||||||
|
'watchConnectPort': watch_connect_port,
|
||||||
|
'watchConnectRetries': watch_connect_retries,
|
||||||
|
'watchConnectTimeout': watch_connect_timeout,
|
||||||
|
'watchConnectInterval': watch_connect_interval
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.debug(('watch settings: watch_link=%(watchLink)s, watch_link_timeout=%(watchLinkTimeout)s, ' +
|
||||||
|
'watch_connect=%(watchConnect)s, watch_connect_host=%(watchConnectHost)s, ' +
|
||||||
|
'watch_connect_port=%(watchConnectPort)s, watch_connect_retries=%(watchConnectRetries)s, ' +
|
||||||
|
'watch_connect_timeout=%(watchConnectTimeout)s, watch_connect_interval=%(watchConnectInterval)s') % s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def _set_watch_settings(s):
|
||||||
|
s.setdefault('watchLink', False)
|
||||||
|
s.setdefault('watchLinkTimeout', 20)
|
||||||
|
s.setdefault('watchConnect', False)
|
||||||
|
s.setdefault('watchConnectHost', 'www.google.com')
|
||||||
|
s.setdefault('watchConnectPort', 80)
|
||||||
|
s.setdefault('watchConnectRetries', 3)
|
||||||
|
s.setdefault('watchConnectTimeout', 5)
|
||||||
|
s.setdefault('watchConnectInterval', 20)
|
||||||
|
|
||||||
|
logging.debug('writing watch settings to %s: ' % WATCH_CONF +
|
||||||
|
('watch_link=%(watchLink)s, watch_link_timeout=%(watchLinkTimeout)s, ' +
|
||||||
|
'watch_connect=%(watchConnect)s, watch_connect_host=%(watchConnectHost)s, ' +
|
||||||
|
'watch_connect_port=%(watchConnectPort)s, watch_connect_retries=%(watchConnectRetries)s, ' +
|
||||||
|
'watch_connect_timeout=%(watchConnectTimeout)s, watch_connect_interval=%(watchConnectInterval)s') % s)
|
||||||
|
|
||||||
|
|
||||||
|
with open(WATCH_CONF, 'w') as f:
|
||||||
|
f.write('link_watch=%s\n' % ['"false"', '"true"'][s['watchLink']])
|
||||||
|
f.write('link_watch_timeout=%s\n' % s['watchLinkTimeout'])
|
||||||
|
f.write('\n')
|
||||||
|
f.write('ip_watch=%s\n' % ['"false"', '"true"'][s['watchLink']])
|
||||||
|
f.write('ip_watch_timeout=%s\n' % s['watchLinkTimeout'])
|
||||||
|
f.write('\n')
|
||||||
|
f.write('%snetwatch_host=%s\n' % (('#' if not s['watchConnect'] else ''), s['watchConnectHost']))
|
||||||
|
f.write('netwatch_port=%s\n' % s['watchConnectPort'])
|
||||||
|
f.write('netwatch_retries=%s\n' % s['watchConnectRetries'])
|
||||||
|
f.write('netwatch_timeout=%s\n' % s['watchConnectTimeout'])
|
||||||
|
f.write('netwatch_interval=%s\n' % s['watchConnectInterval'])
|
||||||
|
|
||||||
|
|
||||||
|
@additional_section
|
||||||
|
def expertSettings():
|
||||||
|
return {
|
||||||
|
'label': 'Expert Settings',
|
||||||
|
'description': 'system tweaks and board-specific options',
|
||||||
|
'advanced': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def watchLink():
|
||||||
|
return {
|
||||||
|
'label': 'Network Link Watch',
|
||||||
|
'description': 'enable this if you want the system to reboot upon detecting network link issues',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_watch_settings,
|
||||||
|
'set': _set_watch_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def watchLinkTimeout():
|
||||||
|
return {
|
||||||
|
'label': 'Network Link Timeout',
|
||||||
|
'description': 'sets the time after which the network link is considered down',
|
||||||
|
'type': 'number',
|
||||||
|
'min': 1,
|
||||||
|
'max': 3600,
|
||||||
|
'unit': 's',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['watchLink'],
|
||||||
|
'get': _get_watch_settings,
|
||||||
|
'set': _set_watch_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def watchConnect():
|
||||||
|
return {
|
||||||
|
'label': 'Connectivity Watch',
|
||||||
|
'description': 'enable this if you want the system to constantly try to connect to a certain host and reboot upon failure',
|
||||||
|
'type': 'bool',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'get': _get_watch_settings,
|
||||||
|
'set': _set_watch_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def watchConnectHost():
|
||||||
|
return {
|
||||||
|
'label': 'Connectivity Watch Host',
|
||||||
|
'description': 'sets the hostname or IP address to which a TCP connection will be opened',
|
||||||
|
'type': 'str',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['watchConnect'],
|
||||||
|
'get': _get_watch_settings,
|
||||||
|
'set': _set_watch_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def watchConnectPort():
|
||||||
|
return {
|
||||||
|
'label': 'Connectivity Watch Port',
|
||||||
|
'description': 'sets the TCP port TO which the TCP connection will be opened',
|
||||||
|
'type': 'number',
|
||||||
|
'min': 1,
|
||||||
|
'max': 65535,
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['watchConnect'],
|
||||||
|
'get': _get_watch_settings,
|
||||||
|
'set': _set_watch_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def watchConnectRetries():
|
||||||
|
return {
|
||||||
|
'label': 'Connectivity Watch Retries',
|
||||||
|
'description': 'sets the number of times to retry to connect',
|
||||||
|
'type': 'number',
|
||||||
|
'min': 1,
|
||||||
|
'max': 100,
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['watchConnect'],
|
||||||
|
'get': _get_watch_settings,
|
||||||
|
'set': _set_watch_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def watchConnectTimeout():
|
||||||
|
return {
|
||||||
|
'label': 'Connectivity Watch Timeout',
|
||||||
|
'description': 'sets the time to wait for the connection to succeed',
|
||||||
|
'type': 'number',
|
||||||
|
'min': 1,
|
||||||
|
'max': 3600,
|
||||||
|
'unit': 's',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['watchConnect'],
|
||||||
|
'get': _get_watch_settings,
|
||||||
|
'set': _set_watch_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@additional_config
|
||||||
|
def watchConnectInterval():
|
||||||
|
return {
|
||||||
|
'label': 'Connectivity Watch Interval',
|
||||||
|
'description': 'sets the time to wait between connections',
|
||||||
|
'type': 'number',
|
||||||
|
'min': 1,
|
||||||
|
'max': 3600,
|
||||||
|
'unit': 's',
|
||||||
|
'section': 'expertSettings',
|
||||||
|
'advanced': True,
|
||||||
|
'reboot': True,
|
||||||
|
'required': True,
|
||||||
|
'depends': ['watchConnect'],
|
||||||
|
'get': _get_watch_settings,
|
||||||
|
'set': _set_watch_settings,
|
||||||
|
'get_set_dict': True
|
||||||
|
}
|
3
package/streameye/Config.in
Normal file
3
package/streameye/Config.in
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
config BR2_PACKAGE_STREAMEYE
|
||||||
|
bool "streameye"
|
||||||
|
|
21
package/streameye/streameye.mk
Normal file
21
package/streameye/streameye.mk
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# streameye
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
STREAMEYE_VERSION = ffd6f28a094f70c70893f6e516610459faa15ea2
|
||||||
|
STREAMEYE_SITE = $(call github,ccrisan,streameye,$(STREAMEYE_VERSION))
|
||||||
|
STREAMEYE_LICENSE = GPLv3
|
||||||
|
|
||||||
|
define STREAMEYE_BUILD_CMDS
|
||||||
|
make CC="$(TARGET_CC)" -C "$(@D)"
|
||||||
|
endef
|
||||||
|
|
||||||
|
define STREAMEYE_INSTALL_TARGET_CMDS
|
||||||
|
cp $(@D)/streameye $(TARGET_DIR)/usr/bin/
|
||||||
|
cp $(@D)/extras/raspimjpeg.py $(TARGET_DIR)/usr/bin/
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(generic-package))
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user