diff --git a/README.md b/README.md index d58045c..f11a638 100644 --- a/README.md +++ b/README.md @@ -57,17 +57,16 @@ This firmware will add the following features: - Telnet server - _Disabled by default._ - FTP server - _Enabled by default._ - Web server - _Enabled by default._ + - The possibility to change some camera settings (copied from official app): + - camera on/off + - video saving mode + - detection sensitivity + - status led + - ir led + - rotate + - PTZ support through a web page. - Proxychains-ng - _Disabled by default. Useful if the camera is region locked._ - The possibility to disable all the cloud features while keeping the RTSP stream. -- In development: - - ONVIF - - A static image snapshot from the web interface. - -This firmware _might_ add: -- Alarm functionality via Telegram (@frekel's [PR #177 in yi-hack-v3](https://github.com/shadow-1/yi-hack-v3/pull/117)) -- Auto upload of the recorded footage to the cloud (eg. Google Drive, Dropbox, etc.) -- Rotation control (on Yi Dome versions of the camera) without need for the app. -- **You decide**, just open an issue with the request. ## Supported cameras @@ -134,6 +133,7 @@ Special thanks to the following people and projects, without them `yi-hack-v4` w - @xmflsct - [https://github.com/xmflsct/yi-hack-1080p](https://github.com/xmflsct/yi-hack-1080p) - @dvv - [Ideas for the RSTP stream](https://github.com/shadow-1/yi-hack-v3/issues/126) - @andy2301 - [Ideas for the RSTP rtsp and rtsp2301](https://github.com/xmflsct/yi-hack-1080p/issues/5#issuecomment-294326131) +- @roleoroleo - [PTZ Implementation](https://github.com/roleoroleo/yi-hack-MStar) --- ### DISCLAIMER diff --git a/VERSION b/VERSION index 0ea3a94..0c62199 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.0 +0.2.1 diff --git a/src/ipc_cmd/.gitignore b/src/ipc_cmd/.gitignore new file mode 100644 index 0000000..e014e8e --- /dev/null +++ b/src/ipc_cmd/.gitignore @@ -0,0 +1,3 @@ +# Ignore the install dir +_install/ + diff --git a/src/ipc_cmd/compile.ipc_cmd b/src/ipc_cmd/compile.ipc_cmd new file mode 100755 index 0000000..1e5cef8 --- /dev/null +++ b/src/ipc_cmd/compile.ipc_cmd @@ -0,0 +1,31 @@ +#!/bin/bash + +export CROSSPATH=/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/bin +export PATH=${PATH}:${CROSSPATH} + +export TARGET=arm-hisiv300-linux +export CROSS=arm-hisiv300-linux +export BUILD=x86_64-pc-linux-gnu + +export CROSSPREFIX=${CROSS}- + +export STRIP=${CROSSPREFIX}strip +export CXX=${CROSSPREFIX}g++ +export CC=${CROSSPREFIX}gcc +export LD=${CROSSPREFIX}ld +export AS=${CROSSPREFIX}as +export AR=${CROSSPREFIX}ar + +SCRIPT_DIR=$(cd `dirname $0` && pwd) +cd $SCRIPT_DIR + +cd ipc_cmd || exit 1 + +make clean +make || exit 1 + +mkdir -p ../_install/bin || exit 1 + +cp ./ipc_cmd ../_install/bin || exit 1 + +arm-hisiv300-linux-strip ../_install/bin/* || exit 1 diff --git a/src/ipc_cmd/init.ipc_cmd b/src/ipc_cmd/init.ipc_cmd new file mode 100755 index 0000000..1039ae8 --- /dev/null +++ b/src/ipc_cmd/init.ipc_cmd @@ -0,0 +1,10 @@ +#!/bin/bash + +SCRIPT_DIR=$(cd `dirname $0` && pwd) +cd $SCRIPT_DIR + +rm -rf ./_install + +cd ipc_cmd + +make clean diff --git a/src/ipc_cmd/install.ipc_cmd b/src/ipc_cmd/install.ipc_cmd new file mode 100755 index 0000000..e2b2235 --- /dev/null +++ b/src/ipc_cmd/install.ipc_cmd @@ -0,0 +1,8 @@ +#!/bin/bash + +SCRIPT_DIR=$(cd `dirname $0` && pwd) +cd $SCRIPT_DIR + +mkdir -p ../../build/home/yi-hack-v4/bin/ || exit 1 + +rsync -av ./_install/* ../../build/home/yi-hack-v4/ || exit 1 diff --git a/src/ipc_cmd/ipc_cmd/Makefile b/src/ipc_cmd/ipc_cmd/Makefile new file mode 100644 index 0000000..a694f30 --- /dev/null +++ b/src/ipc_cmd/ipc_cmd/Makefile @@ -0,0 +1,17 @@ +OBJECTS = ipc_cmd.o +LIBS = -lpthread -lrt + +all: ipc_cmd + +ipc_cmd.o: ipc_cmd.c $(HEADERS) + $(CC) -c $< -fPIC -O2 -o $@ + +ipc_cmd: $(OBJECTS) + $(CC) $(OBJECTS) $(LIBS) -fPIC -O2 -o $@ + $(STRIP) $@ + +.PHONY: clean + +clean: + rm -f ipc_cmd + rm -f $(OBJECTS) diff --git a/src/ipc_cmd/ipc_cmd/ipc_cmd b/src/ipc_cmd/ipc_cmd/ipc_cmd new file mode 100755 index 0000000..8acf1ea Binary files /dev/null and b/src/ipc_cmd/ipc_cmd/ipc_cmd differ diff --git a/src/ipc_cmd/ipc_cmd/ipc_cmd.c b/src/ipc_cmd/ipc_cmd/ipc_cmd.c new file mode 100644 index 0000000..5a29e62 --- /dev/null +++ b/src/ipc_cmd/ipc_cmd/ipc_cmd.c @@ -0,0 +1,342 @@ +/* + * This file is part of libipc (https://github.com/TheCrypt0/libipc). + * Copyright (c) 2019 roleo. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * 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 . + */ + +/* + * Send message to a IPC queue. + */ + +#include "ipc_cmd.h" +#include "getopt.h" + +mqd_t ipc_mq; + +int open_queue() +{ + ipc_mq = mq_open(IPC_QUEUE_NAME, O_RDWR); + if(ipc_mq == -1) { + fprintf(stderr, "Can't open mqueue %s\n", IPC_QUEUE_NAME); + return -1; + } + return 0; +} + +int ipc_start() +{ + int ret = -1; + + ret = open_queue(); + if(ret != 0) { + return -1; + } + + return 0; +} + +void ipc_stop() +{ + if(ipc_mq > 0) { + mq_close(ipc_mq); + } +} + +void print_usage(char *progname) +{ + fprintf(stderr, "\nUsage: %s [t ON/OFF] [-s SENS] [-l LED] [-v WHEN] [-i IR] [-r ROTATE] [-m MOVE] [-p NUM] [-d]\n\n", progname); + fprintf(stderr, "\t-t ON/OFF, --switch ON/OFF\n"); + fprintf(stderr, "\t\tswitch ON or OFF the cam\n"); + fprintf(stderr, "\t-s SENS, --sensitivity SENS\n"); + fprintf(stderr, "\t\tset sensitivity: LOW, MEDIUM or HIGH\n"); + fprintf(stderr, "\t-l LED, --led LED\n"); + fprintf(stderr, "\t\tset led: ON or OFF\n"); + fprintf(stderr, "\t-v WHEN, --save WHEN\n"); + fprintf(stderr, "\t\tset save mode: ALWAYS or DETECT\n"); + fprintf(stderr, "\t-i IR, --ir IR\n"); + fprintf(stderr, "\t\tset ir led: ON or OFF\n"); + fprintf(stderr, "\t-r ROTATE, --rotate ROTATE\n"); + fprintf(stderr, "\t\tset rotate: ON or OFF\n"); + fprintf(stderr, "\t-m MOVE, --move MOVE\n"); + fprintf(stderr, "\t\tsend PTZ command: RIGHT, LEFT, DOWN, UP or STOP\n"); + fprintf(stderr, "\t-p NUM, --preset NUM\n"); + fprintf(stderr, "\t\tsend PTZ go to preset command: NUM = [0..7]\n"); + fprintf(stderr, "\t-f FILE, --file FILE\n"); + fprintf(stderr, "\t\tread binary command from FILE\n"); + fprintf(stderr, "\t-x, --xxx\n"); + fprintf(stderr, "\t\tsend xxx message\n"); + fprintf(stderr, "\t-d, --debug\n"); + fprintf(stderr, "\t\tenable debug\n"); + fprintf(stderr, "\t-h, --help\n"); + fprintf(stderr, "\t\tprint this help\n"); +} + +int main(int argc, char ** argv) +{ + int errno; + char *endptr; + int c, ret; + int switch_on = NONE; + int sensitivity = NONE; + int led = NONE; + int save = NONE; + int ir = NONE; + int rotate = NONE; + int move = NONE; + int preset = NONE; + int debug = 0; + unsigned char preset_msg[20]; + char file[1024]; + unsigned char msg_file[1024]; + FILE *fIn; + int nread = 0; + int xxx = 0; + + file[0] = '\0'; + + while (1) { + static struct option long_options[] = + { + {"switch", required_argument, 0, 't'}, + {"sensitivity", required_argument, 0, 's'}, + {"led", required_argument, 0, 'l'}, + {"save", required_argument, 0, 'v'}, + {"ir", required_argument, 0, 'i'}, + {"rotate", required_argument, 0, 'r'}, + {"move", required_argument, 0, 'm'}, + {"preset", required_argument, 0, 'p'}, + {"file", required_argument, 0, 'f'}, + {"xxx", no_argument, 0, 'x'}, + {"debug", no_argument, 0, 'd'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + /* getopt_long stores the option index here. */ + int option_index = 0; + + c = getopt_long (argc, argv, "t:s:l:v:i:r:m:p:f:xdh", + long_options, &option_index); + + /* Detect the end of the options. */ + if (c == -1) + break; + + switch (c) { + case 't': + if (strcasecmp("on", optarg) == 0) { + switch_on = SWITCH_ON; + } else if (strcasecmp("off", optarg) == 0) { + switch_on = SWITCH_OFF; + } + break; + + case 's': + if (strcasecmp("low", optarg) == 0) { + sensitivity = SENSITIVITY_LOW; + } else if (strcasecmp("medium", optarg) == 0) { + sensitivity = SENSITIVITY_MEDIUM; + } else if (strcasecmp("high", optarg) == 0) { + sensitivity = SENSITIVITY_HIGH; + } + break; + + case 'l': + if (strcasecmp("off", optarg) == 0) { + led = LED_OFF; + } else if (strcasecmp("on", optarg) == 0) { + led = LED_ON; + } + break; + + case 'v': + if (strcasecmp("always", optarg) == 0) { + save = SAVE_ALWAYS; + } else if (strcasecmp("detect", optarg) == 0) { + save = SAVE_DETECT; + } + break; + + case 'i': + if (strcasecmp("off", optarg) == 0) { + ir = IR_OFF; + } else if (strcasecmp("on", optarg) == 0) { + ir = IR_ON; + } + break; + + case 'r': + if (strcasecmp("off", optarg) == 0) { + rotate = ROTATE_OFF; + } else if (strcasecmp("on", optarg) == 0) { + rotate = ROTATE_ON; + } + break; + + case 'm': + if (strcasecmp("right", optarg) == 0) { + move = MOVE_RIGHT; + } else if (strcasecmp("left", optarg) == 0) { + move = MOVE_LEFT; + } else if (strcasecmp("down", optarg) == 0) { + move = MOVE_DOWN; + } else if (strcasecmp("up", optarg) == 0) { + move = MOVE_UP; + } else if (strcasecmp("stop", optarg) == 0) { + move = MOVE_STOP; + } + break; + + case 'p': + errno = 0; /* To distinguish success/failure after call */ + preset = strtol(optarg, &endptr, 10); + + /* Check for various possible errors */ + if ((errno == ERANGE && (preset == LONG_MAX || preset == LONG_MIN)) || (errno != 0 && preset == 0)) { + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + if (endptr == optarg) { + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + break; + + case 'f': + /* Check for various possible errors */ + if (strlen(optarg) < 1023) { + strcpy(file, optarg); + } else { + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + break; + + case 'd': + fprintf (stderr, "debug on\n"); + debug = 1; + break; + + case 'x': + xxx = 1; + break; + + case 'h': + print_usage(argv[0]); + exit(EXIT_SUCCESS); + break; + + case '?': + /* getopt_long already printed an error message. */ + break; + + default: + print_usage(argv[0]); + exit(EXIT_SUCCESS); + } + } + + if (argc == 1) { + print_usage(argv[0]); + exit(EXIT_SUCCESS); + } + + ret=ipc_start(); + if(ret != 0) { + exit(EXIT_FAILURE); + } + + if (switch_on == SWITCH_ON) { + mq_send(ipc_mq, IPC_SWITCH_ON, sizeof(IPC_SWITCH_ON) - 1, 0); + } else if (switch_on == SWITCH_OFF) { + mq_send(ipc_mq, IPC_SWITCH_OFF, sizeof(IPC_SWITCH_OFF) - 1, 0); + } + + if (sensitivity == SENSITIVITY_LOW) { + mq_send(ipc_mq, IPC_SENS_LOW, sizeof(IPC_SENS_LOW) - 1, 0); + } else if (sensitivity == SENSITIVITY_MEDIUM) { + mq_send(ipc_mq, IPC_SENS_MEDIUM, sizeof(IPC_SENS_MEDIUM) - 1, 0); + } else if (sensitivity == SENSITIVITY_HIGH) { + mq_send(ipc_mq, IPC_SENS_HIGH, sizeof(IPC_SENS_HIGH) - 1, 0); + } + + if (led == LED_OFF) { + mq_send(ipc_mq, IPC_LED_OFF, sizeof(IPC_LED_OFF) - 1, 0); + } else if (led == LED_ON) { + mq_send(ipc_mq, IPC_LED_ON, sizeof(IPC_LED_ON) - 1, 0); + } + + if (save == SAVE_ALWAYS) { + mq_send(ipc_mq, IPC_SAVE_ALWAYS, sizeof(IPC_SAVE_ALWAYS) - 1, 0); + } else if (save == SAVE_DETECT) { + mq_send(ipc_mq, IPC_SAVE_DETECT, sizeof(IPC_SAVE_DETECT) - 1, 0); + } + + if (ir == IR_OFF) { + mq_send(ipc_mq, IPC_IR_OFF, sizeof(IPC_IR_OFF) - 1, 0); + } else if (ir == IR_ON) { + mq_send(ipc_mq, IPC_IR_ON, sizeof(IPC_IR_ON) - 1, 0); + } + + if (rotate == ROTATE_OFF) { + mq_send(ipc_mq, IPC_ROTATE_OFF, sizeof(IPC_ROTATE_OFF) - 1, 0); + } else if (rotate == ROTATE_ON) { + mq_send(ipc_mq, IPC_ROTATE_ON, sizeof(IPC_ROTATE_ON) - 1, 0); + } + + if (move == MOVE_RIGHT) { + mq_send(ipc_mq, IPC_MOVE_RIGHT, sizeof(IPC_MOVE_RIGHT) - 1, 0); + } else if (move == MOVE_LEFT) { + mq_send(ipc_mq, IPC_MOVE_LEFT, sizeof(IPC_MOVE_LEFT) - 1, 0); + } else if (move == MOVE_DOWN) { + mq_send(ipc_mq, IPC_MOVE_DOWN, sizeof(IPC_MOVE_DOWN) - 1, 0); + } else if (move == MOVE_UP) { + mq_send(ipc_mq, IPC_MOVE_UP, sizeof(IPC_MOVE_UP) - 1, 0); + } else if (move == MOVE_STOP) { + mq_send(ipc_mq, IPC_MOVE_STOP, sizeof(IPC_MOVE_STOP) - 1, 0); + } + + if (preset != NONE) { + memcpy(preset_msg, IPC_GOTO_PRESET, sizeof(IPC_GOTO_PRESET) - 1); + preset_msg[16] = preset & 0xff; + mq_send(ipc_mq, preset_msg, sizeof(IPC_GOTO_PRESET) - 1, 0); + } + + if (file[0] != '\0') { + fIn = fopen(file, "r"); + if (fIn == NULL) { + fprintf(stderr, "Error opening file %s\n", file); + exit(EXIT_FAILURE); + } + + // Tell size + fseek(fIn, 0L, SEEK_END); + nread = ftell(fIn); + fseek(fIn, 0L, SEEK_SET); + + if (fread(msg_file, 1, nread, fIn) != nread) { + fprintf(stderr, "Error reading file %s\n", file); + exit(EXIT_FAILURE); + } + fclose(fIn); + mq_send(ipc_mq, msg_file, nread, 0); + } + + if (xxx == 1) { + mq_send(ipc_mq, IPC_XXX_0, sizeof(IPC_XXX_0) - 1, 0); + } + + ipc_stop(); + + return 0; +} diff --git a/src/ipc_cmd/ipc_cmd/ipc_cmd.h b/src/ipc_cmd/ipc_cmd/ipc_cmd.h new file mode 100644 index 0000000..66273ca --- /dev/null +++ b/src/ipc_cmd/ipc_cmd/ipc_cmd.h @@ -0,0 +1,89 @@ +/* + * This file is part of libipc (https://github.com/TheCrypt0/libipc). + * Copyright (c) 2019 roleo. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IPC_QUEUE_NAME "/ipc_dispatch" +#define IPC_MESSAGE_MAX_SIZE 512 + +#define NONE -1 + +#define IPC_SWITCH_OFF "\x02\x00\x00\x00\x08\x00\x00\x00\x75\x00\x01\x00\x00\x00\x00\x00" +#define IPC_SWITCH_ON "\x02\x00\x00\x00\x08\x00\x00\x00\x74\x00\x01\x00\x00\x00\x00\x00" + +#define SWITCH_OFF 0 +#define SWITCH_ON 1 + +#define IPC_SENS_HIGH "\x01\x00\x00\x00\x08\x00\x00\x00\x27\x10\x01\x00\x04\x00\x00\x00\x00\x00\x00\x00" +#define IPC_SENS_MEDIUM "\x01\x00\x00\x00\x08\x00\x00\x00\x27\x10\x01\x00\x04\x00\x00\x00\x01\x00\x00\x00" +#define IPC_SENS_LOW "\x01\x00\x00\x00\x08\x00\x00\x00\x27\x10\x01\x00\x04\x00\x00\x00\x02\x00\x00\x00" + +#define SENSITIVITY_HIGH 0 +#define SENSITIVITY_MEDIUM 1 +#define SENSITIVITY_LOW 2 + +#define IPC_LED_OFF "\x02\x00\x00\x00\x08\x00\x00\x00\x77\x00\x01\x00\x00\x00\x00\x00" +#define IPC_LED_ON "\x02\x00\x00\x00\x08\x00\x00\x00\x76\x00\x01\x00\x00\x00\x00\x00" + +#define LED_OFF 0 +#define LED_ON 1 + +#define IPC_SAVE_ALWAYS "\x02\x00\x00\x00\x08\x00\x00\x00\x79\x00\x01\x00\x00\x00\x00\x00" +#define IPC_SAVE_DETECT "\x02\x00\x00\x00\x08\x00\x00\x00\x78\x00\x01\x00\x00\x00\x00\x00" + +#define SAVE_ALWAYS 0 +#define SAVE_DETECT 1 + +#define IPC_IR_OFF "\x02\x00\x00\x00\x08\x00\x00\x00\x24\x10\x01\x00\x04\x00\x00\x00\x02\x00\x00\x00" +#define IPC_IR_ON "\x02\x00\x00\x00\x08\x00\x00\x00\x24\x10\x01\x00\x04\x00\x00\x00\x01\x00\x00\x00" + +#define IR_OFF 0 +#define IR_ON 1 + +#define IPC_ROTATE_OFF "\x02\x00\x00\x00\x08\x00\x00\x00\x7b\x00\x01\x00\x00\x00\x00\x00" +#define IPC_ROTATE_ON "\x02\x00\x00\x00\x08\x00\x00\x00\x7a\x00\x01\x00\x00\x00\x00\x00" + +#define ROTATE_OFF 0 +#define ROTATE_ON 1 + +#define IPC_MOVE_RIGHT "\x01\x00\x00\x00\x08\x00\x00\x00\x06\x40\x06\x40\x18\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00" +#define IPC_MOVE_LEFT "\x01\x00\x00\x00\x08\x00\x00\x00\x06\x40\x06\x40\x18\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00" +#define IPC_MOVE_DOWN "\x01\x00\x00\x00\x08\x00\x00\x00\x06\x40\x06\x40\x18\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00" +#define IPC_MOVE_UP "\x01\x00\x00\x00\x08\x00\x00\x00\x06\x40\x06\x40\x18\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" +#define IPC_MOVE_STOP "\x01\x00\x00\x00\x08\x00\x00\x00\x07\x40\x01\x00\x00\x00\x00\x00" + +#define MOVE_RIGHT 0 +#define MOVE_LEFT 1 +#define MOVE_DOWN 2 +#define MOVE_UP 3 +#define MOVE_STOP 4 + +#define IPC_GOTO_PRESET "\x01\x00\x00\x00\x08\x00\x00\x00\x02\x40\x01\x00\x04\x00\x00\x00\xff\x00\x00\x00" + +#define GOTO_PRESET 0 + +#define IPC_XXX_0 "\x01\x00\x00\x00\x04\x00\x00\x00\x71\x00\x71\x00\x00\x00\x00\x00\xa1\x0e\x9a\x5e" diff --git a/src/ipc_cmd/ipc_cmd/ipc_cmd.o b/src/ipc_cmd/ipc_cmd/ipc_cmd.o new file mode 100644 index 0000000..34a0646 Binary files /dev/null and b/src/ipc_cmd/ipc_cmd/ipc_cmd.o differ diff --git a/src/static/static/home/yi-hack-v4/etc/camera.conf b/src/static/static/home/yi-hack-v4/etc/camera.conf new file mode 100644 index 0000000..4c14dd1 --- /dev/null +++ b/src/static/static/home/yi-hack-v4/etc/camera.conf @@ -0,0 +1,6 @@ +SWITCH_ON=yes +SAVE_VIDEO_ON_MOTION=yes +SENSITIVITY=low +LED=no +ROTATE=no +IR=yes diff --git a/src/www/httpd/cgi-bin/camera_settings.sh b/src/www/httpd/cgi-bin/camera_settings.sh new file mode 100755 index 0000000..70f4496 --- /dev/null +++ b/src/www/httpd/cgi-bin/camera_settings.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +YI_HACK_PREFIX="/home/yi-hack-v4" + +CONF_LAST="CONF_LAST" + +for I in 1 2 3 4 5 6 +do + CONF="$(echo $QUERY_STRING | cut -d'&' -f$I | cut -d'=' -f1)" + VAL="$(echo $QUERY_STRING | cut -d'&' -f$I | cut -d'=' -f2)" + + if [ $CONF == $CONF_LAST ]; then + continue + fi + CONF_LAST=$CONF + + if [ "$CONF" == "switch_on" ] ; then + if [ "$VAL" == "no" ] ; then + ipc_cmd -t off + else + ipc_cmd -t on + fi + elif [ "$CONF" == "save_video_on_motion" ] ; then + if [ "$VAL" == "no" ] ; then + ipc_cmd -v always + else + ipc_cmd -v detect + fi + elif [ "$CONF" == "sensitivity" ] ; then + ipc_cmd -s $VAL + elif [ "$CONF" == "led" ] ; then + if [ "$VAL" == "no" ] ; then + ipc_cmd -l off + else + ipc_cmd -l on + fi + elif [ "$CONF" == "ir" ] ; then + if [ "$VAL" == "no" ] ; then + ipc_cmd -i off + else + ipc_cmd -i on + fi + elif [ "$CONF" == "rotate" ] ; then + if [ "$VAL" == "no" ] ; then + ipc_cmd -r off + else + ipc_cmd -r on + fi + fi + sleep 1 +done + +printf "Content-type: application/json\r\n\r\n" + +printf "{\n" +printf "}" diff --git a/src/www/httpd/cgi-bin/preset.sh b/src/www/httpd/cgi-bin/preset.sh new file mode 100755 index 0000000..3bfc5b7 --- /dev/null +++ b/src/www/httpd/cgi-bin/preset.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +NUM=-1 + +CONF="$(echo $QUERY_STRING | cut -d'=' -f1)" +VAL="$(echo $QUERY_STRING | cut -d'=' -f2)" + +if [ "$CONF" == "num" ] ; then + NUM=$VAL +fi + +if [ $NUM -ne -1 ] ; then + ipc_cmd -p $NUM +fi + +printf "Content-type: application/json\r\n\r\n" + +printf "{\n" +printf "}" diff --git a/src/www/httpd/cgi-bin/ptz.sh b/src/www/httpd/cgi-bin/ptz.sh new file mode 100755 index 0000000..fcebf21 --- /dev/null +++ b/src/www/httpd/cgi-bin/ptz.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +DIR="none" +TIME="0.1" + +for I in 1 2 +do + CONF="$(echo $QUERY_STRING | cut -d'&' -f$I | cut -d'=' -f1)" + VAL="$(echo $QUERY_STRING | cut -d'&' -f$I | cut -d'=' -f2)" + + if [ "$CONF" == "dir" ] ; then + DIR="-m $VAL" + elif [ "$CONF" == "time" ] ; then + TIME="$VAL" + fi +done + +if [ "$DIR" != "none" ] ; then + ipc_cmd $DIR + sleep $TIME + ipc_cmd -m stop +fi + +printf "Content-type: application/json\r\n\r\n" + +printf "{\n" +printf "}" diff --git a/src/www/httpd/htdocs/images/arrow-down-bold-box-outline.png b/src/www/httpd/htdocs/images/arrow-down-bold-box-outline.png new file mode 100644 index 0000000..27fb229 Binary files /dev/null and b/src/www/httpd/htdocs/images/arrow-down-bold-box-outline.png differ diff --git a/src/www/httpd/htdocs/images/arrow-left-bold-box-outline.png b/src/www/httpd/htdocs/images/arrow-left-bold-box-outline.png new file mode 100644 index 0000000..1cbb344 Binary files /dev/null and b/src/www/httpd/htdocs/images/arrow-left-bold-box-outline.png differ diff --git a/src/www/httpd/htdocs/images/arrow-right-bold-box-outline.png b/src/www/httpd/htdocs/images/arrow-right-bold-box-outline.png new file mode 100644 index 0000000..c7009a5 Binary files /dev/null and b/src/www/httpd/htdocs/images/arrow-right-bold-box-outline.png differ diff --git a/src/www/httpd/htdocs/images/arrow-up-bold-box-outline.png b/src/www/httpd/htdocs/images/arrow-up-bold-box-outline.png new file mode 100644 index 0000000..0686974 Binary files /dev/null and b/src/www/httpd/htdocs/images/arrow-up-bold-box-outline.png differ diff --git a/src/www/httpd/htdocs/index.html b/src/www/httpd/htdocs/index.html index 29c612f..3b81078 100755 --- a/src/www/httpd/htdocs/index.html +++ b/src/www/httpd/htdocs/index.html @@ -57,18 +57,21 @@
  • -
  • - Status -
  • Configurations
  • MQTT
  • +
  • + Camera Settings +
  • RTSP
  • +
  • + PTZ +
  • Update
  • diff --git a/src/www/httpd/htdocs/js/modules/camera_settings.js b/src/www/httpd/htdocs/js/modules/camera_settings.js new file mode 100644 index 0000000..8e237b5 --- /dev/null +++ b/src/www/httpd/htdocs/js/modules/camera_settings.js @@ -0,0 +1,90 @@ +var APP = APP || {}; + +APP.camera_settings = (function ($) { + + function init() { + registerEventHandler(); + fetchConfigs(); + } + + function registerEventHandler() { + $(document).on("click", '#button-save', function (e) { + saveConfigs(); + }); + } + + function fetchConfigs() { + loadingStatusElem = $('#loading-status'); + loadingStatusElem.text("Loading..."); + + $.ajax({ + type: "GET", + url: 'cgi-bin/get_configs.sh?conf=camera', + dataType: "json", + success: function(response) { + loadingStatusElem.fadeOut(500); + + $.each(response, function (key, state) { + if(key=="SENSITIVITY") + $('select[data-key="' + key +'"]').prop('value', state); + else + $('input[type="checkbox"][data-key="' + key +'"]').prop('checked', state === 'yes'); + }); + }, + error: function(response) { + console.log('error', response); + } + }); + } + + function saveConfigs() { + var saveStatusElem; + let configs = {}; + + saveStatusElem = $('#save-status'); + + saveStatusElem.text("Saving..."); + + $('.configs-switch input[type="checkbox"]').each(function () { + configs[$(this).attr('data-key')] = $(this).prop('checked') ? 'yes' : 'no'; + }); + + configs["SENSITIVITY"] = $('select[data-key="SENSITIVITY"]').prop('value'); + + $.ajax({ + type: "POST", + url: 'cgi-bin/set_configs.sh?conf=camera', + data: configs, + dataType: "json", + success: function(response) { + saveStatusElem.text("Saved"); + }, + error: function(response) { + saveStatusElem.text("Error while saving"); + console.log('error', response); + } + }); + $.ajax({ + type: "GET", + url: 'cgi-bin/camera_settings.sh?' + + 'save_video_on_motion=' + configs["SAVE_VIDEO_ON_MOTION"] + + '&sensitivity=' + configs["SENSITIVITY"] + + '&led=' + configs["LED"] + + '&ir=' + configs["IR"] + + '&rotate=' + configs["ROTATE"] + + '&switch_on=' + configs["SWITCH_ON"], + dataType: "json", + success: function(response) { + + }, + error: function(response) { + console.log('error', response); + } + }); + } + + return { + init: init + }; + +})(jQuery); diff --git a/src/www/httpd/htdocs/js/modules/ptz.js b/src/www/httpd/htdocs/js/modules/ptz.js new file mode 100644 index 0000000..706cdfa --- /dev/null +++ b/src/www/httpd/htdocs/js/modules/ptz.js @@ -0,0 +1,63 @@ +var APP = APP || {}; + +APP.ptz = (function ($) { + + function init() { + registerEventHandler(); + } + + function registerEventHandler() { + $(document).on("click", '#img-au', function (e) { + move('#img-au', 'up'); + }); + $(document).on("click", '#img-al', function (e) { + move('#img-al', 'left'); + }); + $(document).on("click", '#img-ar', function (e) { + move('#img-ar', 'right'); + }); + $(document).on("click", '#img-ad', function (e) { + move('#img-ad', 'down'); + }); + $(document).on("click", '#button-goto', function (e) { + gotoPreset('#button-goto', '#select-goto'); + }); + } + + function move(button, dir) { + $(button).attr("disabled", true); + $.ajax({ + type: "GET", + url: 'cgi-bin/ptz.sh?dir='+dir, + dataType: "json", + error: function(response) { + console.log('error', response); + $(button).attr("disabled", false); + }, + success: function(data) { + $(button).attr("disabled", false); + } + }); + } + + function gotoPreset(button, select) { + $(button).attr("disabled", true); + $.ajax({ + type: "GET", + url: 'cgi-bin/preset.sh?num='+$(select + " option:selected").text(), + dataType: "json", + error: function(response) { + console.log('error', response); + $(button).attr("disabled", false); + }, + success: function(data) { + $(button).attr("disabled", false); + } + }); + } + + return { + init: init + }; + +})(jQuery); diff --git a/src/www/httpd/htdocs/pages/camera_settings.html b/src/www/httpd/htdocs/pages/camera_settings.html new file mode 100644 index 0000000..dab6230 --- /dev/null +++ b/src/www/httpd/htdocs/pages/camera_settings.html @@ -0,0 +1,121 @@ +
    +
    +
    +
    + +
    +
    +
    +
    +
    +

    + On this page you can change some camera settings. +

    +
    +

    General

    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Switch on/off the camera + + + Switch on/off the video on the camera. + +
    Save video when a motion is detected + + + If enabled, video will be saved only when a motion is detected. + +
    + + If disabled, video will be always saved. + +
    + + (It takes effect only if recording is enabled) + +
    Detection sensitivity +
    + +
    +
    Status led + + + Set status led on or off. + +
    IR led + + + Enable IR led for night vision. + +
    Rotate + + + Enable image rotation for ceiling mount. + +
    +
    +
    +
    + Any change will take effect immediately. +
    + Note that these settings are not synchronized with the settings made with the app. +
    +
    +
    +
    + +
    +
    +
    diff --git a/src/www/httpd/htdocs/pages/ptz.html b/src/www/httpd/htdocs/pages/ptz.html new file mode 100644 index 0000000..6b68859 --- /dev/null +++ b/src/www/httpd/htdocs/pages/ptz.html @@ -0,0 +1,64 @@ +
    +
    + +
    +
    +

    + In this page you can move your cam. +

    +
    + + +
    +

    Move pad

    +
    + + + + + + + + + + + + + + + + + + +
    + +

    Presets

    +
    + + + + + + + +
    + + + +
    +
    +
    +