11 files changed, 0 insertions(+), 709 deletions(-)
D background_scripts/copy_print.py
D background_scripts/office_door_motion.py
D background_scripts/vosk_dump.py
D security sensors/sensors.py
D security sensors/settings.txt
D security sensors/setup.txt
D security sensors/startup.sh
D security sensors/templates/fail.html
D security sensors/templates/form.html
D security sensors/templates/index.html
D security sensors/templates/pass.html
D background_scripts/copy_print.py => background_scripts/copy_print.py +0 -73
@@ 1,73 0,0 @@
-#!/usr/bin/python3
-#home-butler
-#Copyright (C) 2022 David Hamner
-
-#This program is free software: you can redistribute it and/or modify
-#it under the terms of the GNU General Public License as published by
-#the Free Software Foundation, either version 3 of the License, or
-#(at your option) any later version.
-
-#This program is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-#GNU General Public License for more details.
-
-#You should have received a copy of the GNU General Public License
-#along with this program. If not, see <http://www.gnu.org/licenses/>.
-import os
-import time
-import requests
-from butler_common import *
-#print("cancel print")
-current_voice_cmd = ""
-#cmd = "curl -k4 --request POST -H '" + OCTOPRINT_API_KEY + "' -H 'Content-Type: application/json' --data '{\"command\":\"cancel\"}' http://10.250.10.207/api/job"
-cmd = "curl -k4 --request GET -H '" + OCTOPRINT_API_KEY + "' -H 'Content-Type: application/json' http://10.250.10.207/api/job"
-result = subprocess.run(cmd, stdout=subprocess.PIPE, shell=True)
-data = json.loads(result.stdout.decode())
-print(data['job']['file']['name'])
-print(data['state'])
-#cmd = "espeak 'canceling print disabled'"
-#os.system(cmd)
-
-master = "http://10.250.10.207"
-slave = "http://10.250.10.15"
-
-last_state = ""
-
-while True:
-
- cmd = "curl -k4 --request GET -H '" + OCTOPRINT_API_KEY + "' -H 'Content-Type: application/json' http://10.250.10.207/api/job"
- result = subprocess.run(cmd, stdout=subprocess.PIPE, shell=True)
- try:
- data = json.loads(result.stdout.decode())
- except Exception:
- print("Octoprint likely not running")
- time.sleep(10)
- continue
- new_state = data['state']
- if last_state == "Operational" and new_state == "Printing":
- file_name = data['job']['file']['name']
-
- #Download from master
- gcode_url = f"{master}/downloads/files/local/{file_name}"
- cmd = "curl -k4 --request GET -H '" + OCTOPRINT_API_KEY + f"' -H 'Content-Type: application/json' {gcode_url}"
- result = subprocess.run(cmd, stdout=subprocess.PIPE, shell=True)
- gcode = result.stdout.decode()
- with open(f"/tmp/{file_name}", "w+") as fh:
- fh.write(gcode)
-
- #upload to slave
- cmd = f'curl -k -H "{OCTOPRINT_API_KEY}" -F "select=false" -F "print=false" -F "file=@/tmp/{file_name}" "{slave}/api/files/local"'
- print(cmd)
- result = subprocess.run(cmd, stdout=subprocess.PIPE, shell=True)
- print(result.stdout.decode())
-
- #Tringer print
- cmd = "curl -k4 --request POST -H '" + OCTOPRINT_API_KEY + "' -H 'Content-Type: application/json' --data '{\"command\":\"select\",\"print\":true}' " + slave + "/api/files/local/" + file_name
- os.system(cmd)
-
- print (f"Mirror job started {file_name}")
- else:
- print(f"status: {new_state}")
- last_state = new_state
- time.sleep(10)
D background_scripts/office_door_motion.py => background_scripts/office_door_motion.py +0 -71
@@ 1,71 0,0 @@
-#!/usr/bin/python3
-
-
-#GPL3 based on: https://github.com/jb-0001/object-motion-detection
-
-import os
-import cv2
-
-
-
-video = cv2.VideoCapture("rtsp://10.250.10.15:8554/unicast")
-
-"""
-while(True):
- ret, frame = video.read()
- cv2.imshow('VIDEO', frame)
- cv2.waitKey(1)
-"""
-
-
-ret, frame1 = video.read()
-ret, frame2 = video.read()
-
-lastPose = -1
-num_move_frames = 0
-while video.isOpened():
- difference = cv2.absdiff(frame1, frame2)
- grayscale = cv2.cvtColor(difference, cv2.COLOR_BGR2GRAY)
- blur = cv2.GaussianBlur(grayscale, (5, 5), 0)
- _, threshold = cv2.threshold(blur, 35, 255, cv2.THRESH_BINARY)
- dilated = cv2.dilate(threshold, None, iterations=2)
- contours, _ = cv2.findContours(
- dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
-
- for contour in contours:
- (x, y, w, h) = cv2.boundingRect(contour)
- if cv2.contourArea(contour) < 950:
- continue
- cv2.drawContours(frame1, contours, -1, (0, 255, 0), 1)
- cv2.rectangle(frame1, (x, y), (x+w, y+h), (120, 0, 150), 2)
- lastPose = x
- if contours != []:
- num_move_frames = num_move_frames + 1
- #print(f"Updating lastPose: {lastPose}")
- if contours == []:
- if lastPose != -1:
- print(f"End of movement: {lastPose}, amount: {num_move_frames}")
- if num_move_frames < 35:
- print(f"Motion to fast: {num_move_frames}")
- elif num_move_frames > 90:
- print(f"Motion too slow: {num_move_frames}")
- elif lastPose < 200:
- print("Welcome to the office")
- os.system(f"curl 10.250.10.133:5000/person_entered_office")
- else:
- print("Bye for now")
- os.system(f"curl 10.250.10.133:5000/person_exited_office")
- lastPose = -1
- num_move_frames = 0
- #cv2.imshow("feed", frame1)
- cv2.waitKey(1)
- frame1 = frame2
- ret, frame2 = video.read()
-
-
-
-
-cv2.destroyAllWindows()
-video.release()
-
-
D background_scripts/vosk_dump.py => background_scripts/vosk_dump.py +0 -133
@@ 1,133 0,0 @@
-#!/usr/bin/env python3
-
-import argparse
-import os
-import queue
-import sounddevice as sd
-import vosk
-import sys
-import urllib.parse
-
-script_path = os.path.realpath(os.path.abspath(__file__))
-script_dir = os.path.dirname(script_path)
-print(script_dir)
-os.chdir(script_dir)
-
-q = queue.Queue()
-
-def int_or_str(text):
- """Helper function for argument parsing."""
- try:
- return int(text)
- except ValueError:
- return text
-
-def callback(indata, frames, time, status):
- """This is called (from a separate thread) for each audio block."""
- #if status:
- #print(status, file=sys.stderr)
- q.put(bytes(indata))
-
-parser = argparse.ArgumentParser(add_help=False)
-parser.add_argument(
- '-l', '--list-devices', action='store_true',
- help='show list of audio devices and exit')
-args, remaining = parser.parse_known_args()
-if args.list_devices:
- print(sd.query_devices())
- parser.exit(0)
-parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- parents=[parser])
-parser.add_argument(
- '-f', '--filename', type=str, metavar='FILENAME',
- help='audio file to store recording to')
-parser.add_argument(
- '-m', '--model', type=str, metavar='MODEL_PATH',
- help='Path to the model')
-parser.add_argument(
- '-d', '--device', type=int_or_str,
- help='input device (numeric ID or substring)')
-parser.add_argument(
- '-r', '--samplerate', type=int, help='sampling rate')
-args = parser.parse_args(remaining)
-
-try:
- if args.model is None:
- args.model = "model"
- if not os.path.exists(args.model):
- print ("Please download a model for your language from https://alphacephei.com/vosk/models")
- print ("and unpack as 'model' in the current folder.")
- parser.exit(0)
- if args.samplerate is None:
- device_info = sd.query_devices(args.device, 'input')
- # soundfile expects an int, sounddevice provides a float:
- args.samplerate = int(device_info['default_samplerate'])
-
- model = vosk.Model(args.model)
-
- if args.filename:
- dump_fn = open(args.filename, "wb")
- else:
- dump_fn = None
-
- with sd.RawInputStream(samplerate=args.samplerate, blocksize = 8000, device=args.device, dtype='int16',
- channels=1, callback=callback):
- print('#' * 80)
- print('Press Ctrl+C to stop the recording')
- print('#' * 80)
-
- #rec = vosk.KaldiRecognizer(model, )
- rec = vosk.KaldiRecognizer(model, args.samplerate)
- processed_words = ""
- while True:
- data = q.get()
- ok = rec.AcceptWaveform(data)
- if ok:
-
- cmd = rec.Result().split('"')[-2]
- if cmd.startswith("the"):
- cmd = cmd[3:].strip()
-
- processed_words = ""
- #print(f"\nCMD: {cmd}\n")
- #url_cmd = urllib.parse.quote(cmd)
- cmd = f"curl 'http://10.250.10.133:5000/voice_cmd_reset'"
- #print(cmd)
- os.system(cmd)
- #print(rec.Result())
- else:
- new_word = ""
- part = rec.PartialResult().split('"')[-2]
- if part.startswith("the"):
- part = part[3:].strip()
- if processed_words in part:
- if processed_words != "":
- new_word = part.split(processed_words)[-1]
- else:
- new_word = part
- elif len(processed_words.split(" ")) > 1:
- num_words_to_keep = len(part.split(" ")) - len(processed_words.split(" "))
- if num_words_to_keep <= 1:
- new_word = " ".join(part.split(" ")[:num_words_to_keep*-1])
- else:
- new_word = part
- if new_word != "":
- print(f"\rNew: {new_word}")
- new_word = new_word.strip()
- processed_words = part
- url_cmd = urllib.parse.quote(new_word)
- cmd = f"curl 'http://10.250.10.133:5000/voice_cmd_update/{url_cmd}'"
- #print(cmd)
- os.system(cmd)
-
- #print(f"Part: {part}",end='\r')
- #if dump_fn is not None:
- #dump_fn.write(data)
-
-except KeyboardInterrupt:
- print('\nDone')
- parser.exit(0)
-except Exception as e:
- parser.exit(type(e).__name__ + ': ' + str(e))
D security sensors/sensors.py => security sensors/sensors.py +0 -328
@@ 1,328 0,0 @@
-#!/usr/bin/python3
-#home-butler
-#GNU LGPL v3
-#Copyright (C) 2022 David Hamner
-#hamner@librem.one
-
-#This program is free software; you can redistribute it and/or
-#modify it under the terms of the GNU Lesser 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
-#Lesser General Public License for more details.
-
-#You should have received a copy of the GNU Lesser General Public License
-#along with this program; if not, write to the Free Software Foundation,
-#Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-import cv2
-import numpy as np
-from datetime import datetime
-import time
-from threading import Thread
-import subprocess
-import os
-import json
-from signal import signal, SIGINT
-from flask_opencv_streamer.streamer import Streamer
-import torch, detectron2
-TORCH_VERSION = ".".join(torch.__version__.split(".")[:2])
-CUDA_VERSION = torch.__version__.split("+")[-1]
-print("torch: ", TORCH_VERSION, "; cuda: ", CUDA_VERSION)
-print("detectron2:", detectron2.__version__)
-import detectron2
-from detectron2.utils.logger import setup_logger
-setup_logger()
-# import some common libraries
-import numpy as np
-import os, json, cv2, random
-# import some common detectron2 utilities
-from detectron2 import model_zoo
-from detectron2.engine import DefaultPredictor
-from detectron2.config import get_cfg
-from detectron2.utils.visualizer import Visualizer
-from detectron2.data import MetadataCatalog, DatasetCatalog
-cfg = get_cfg()
-# add project-specific config (e.g., TensorMask) here if you're not running a model in detectron2's core library
-cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"))
-cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5 # set threshold for this model
-# Find a model from detectron2's model zoo. You can use the https://dl.fbaipublicfiles... url as well
-cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")
-predictor = DefaultPredictor(cfg)
-
-
-port = 2468
-require_login = False
-
-
-#Thank you to: https://github.com/abhishek305/Motion-capture-using-opencv-contours/blob/master/Contours%20Opencv.py
-#Some of this was based on ^^^
-script_path = os.path.realpath(os.path.abspath(__file__))
-script_dir = os.path.dirname(script_path)
-event_base = f"{script_dir}/events/"
-if not os.path.isdir(event_base):
- os.mkdir(event_base)
-
-#Main settings
-boarder = 70
-num_frames_needed_to_trigger = 3
-num_frames_needed_to_end_trigger = 10
-min_move_area = 600
-triger_move_area = 12000
-too_many_motion_points = 400
-
-max_back_log = 3
-eyes_busy = False
-
-
-#cam_devices= {"Potato": "rtsp://10.250.10.225:554/Streaming/Channes/ID/?transportmode=unicast"}
-#cap=cv2.VideoCapture("rtsp://10.250.10.225:554/Streaming/Channes/ID/?transportmode=unicast")
-
-exit = False
-
-
-def load_settings():
- cam_devices = {}
- settings_file_path = f"{script_dir}/settings.txt"
- with open(settings_file_path) as settings_file:
- for config_line in settings_file.readlines():
- if config_line.startswith("#") or config_line.strip() == "":
- continue
- raw_data = config_line.strip().split("~")
- name = raw_data[0]
- device = raw_data[1]
- cam_devices[name] = device
- return(cam_devices)
-cam_devices = load_settings()
-print(cam_devices)
-
-
-def what_is_this(file_name):
- global eyes_busy
- global predictor
- eyes_busy = True
- found_objs = []
-
- im = cv2.imread(file_name)
-
- with torch.no_grad():
- outputs = predictor(im)
- instances = outputs["instances"]
- detected_class_indexes = instances.pred_classes
- prediction_boxes = instances.pred_boxes
- metadata = MetadataCatalog.get(cfg.DATASETS.TRAIN[0])
- class_catalog = metadata.thing_classes
-
- #Thank you to: https://stackoverflow.com/a/68471952
- for idx, coordinates in enumerate(prediction_boxes):
- class_index = detected_class_indexes[idx]
- class_name = class_catalog[class_index]
- found_objs.append(class_name)
- print(class_name, coordinates)
-
- #Clean up ram
- #del(predictor)
- del(outputs)
- del(instances)
- del(detected_class_indexes)
- del(prediction_boxes)
- del(metadata)
- del(class_catalog)
-
- eyes_busy = False
-
- #cmd = f"lumi predict --checkpoint=fast".split(" ")
- #cmd.append(file_name)
- #OUT = subprocess.Popen(cmd, stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
- #stdout,stderr = OUT.communicate()
- #stdout = stdout.decode().strip()
- #if "\n" in stdout:
- # raw_text = stdout.split('\n')[-1]
- # result = json.loads(raw_text)
- # eyes_busy = False
- # for obj in result['objects']:
- # name = obj['label']
- # if name not in found_objs:
- # found_objs.append(name)
- if found_objs != []:
- new_name = "_".join(found_objs)
- old_name = file_name.split('/')[-1]
- full_new_name = os.path.dirname(file_name)
- full_new_name = f"{full_new_name}/{new_name}_{old_name}"
- os.rename(file_name, full_new_name)
- print(found_objs)
- return(found_objs)
- #print(stderr)
-
-def main_cam_loop(cam_name, dev_name):
- global exit
- global port
-
- streamer = Streamer(port, require_login)
- print(f"Sarting {cam_name}, Dev: {dev_name}, on port: {port}")
- port = port + 1
-
- cap = cv2.VideoCapture(dev_name)
- if cap.isOpened():
- ret,frame = cap.read()
- else:
- ret =False
- if not ret:
- print(f"Error with {dev_name} {cam_name}")
- return
- cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
- cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
-
- ret,frame1 = cap.read()
- ret,frame2 = cap.read()
-
- back_log = []
- move_frames = 0
- event_path = ""
- sleepy_frames = 0 # used to keep track of number of non moving frames
- video_to_save = ""
- fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
- start_time = time.time()
- frame_count = 0
- fps = 1
-
-
- while not exit:
- ret,frame = cap.read()
- #frame = cv2.fastNlMeansDenoisingColored(frame,None,10,10,7,21)
- time_now = time.time()
- time_taken = time_now - start_time
- start_time = time_now
- fps = 1/time_taken
- print(f"{cam_name} FPS: {fps}")
- d=cv2.absdiff(frame1,frame2)
- try:
- grey=cv2.cvtColor(d,cv2.COLOR_BGR2GRAY)
- except Exception:
- print("Error pulling frame from...")
- continue
- blur =cv2.GaussianBlur(grey,(5,5),0)
- ret,th=cv2.threshold(blur,20,255,cv2.THRESH_BINARY)
- dilated=cv2.dilate(th,np.ones((3,3),np.uint8),iterations=3)
- #img,c,h=cv2.findContours(dilated,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
- contours, hierarchy = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
-
-
- #Check if frame is moving
- if len(contours) > too_many_motion_points:
- count = len(contours)
- print(f"Warning, Too much moving! {count}")
- contours = []
- found_moving = False
- for i in contours:
- if cv2.contourArea(i) < min_move_area:
- continue
- (x, y, w, h) = cv2.boundingRect(i)
- size = w * h
-
- if size > triger_move_area:
- found_moving = True
- if move_frames > num_frames_needed_to_trigger:
- ts = time.strftime('%l:%M%p_(+%S)_on_%b_%d_%Y')
- local_event_base = f"{event_base}/{cam_name}"
- if not os.path.isdir(local_event_base):
- os.mkdir(local_event_base)
- #ts = f"{ }_at_{ts}"
- if event_path == "":
- event_path = f"{local_event_base}/{ts}/"
- print(f"New event: {ts}")
- os.mkdir(event_path)
- #video_to_save = cv2.VideoWriter(f'{script_dir}/{ts}/event.avi', -1, 20.0, (1920,1080))
- height, width = frame1.shape[:2]
- shape = (width, height)
- video_to_save = cv2.VideoWriter(f'{local_event_base}/{ts}/event.mp4', fourcc, fps, shape)
- cv2.rectangle(frame1, (x-boarder, y-boarder), (x + w+boarder, y + h+boarder), (0, 0, 255), 2)
-
- #expand boarder around moving item
- x_start = x-boarder
- if x_start < 0:
- x_start = 0
- x_end = x + w+boarder
- if x_end > frame1.shape[1]:
- x_end = frame1.shape[1]
- y_start = y-boarder
- if y_start < 0:
- y_start = 0
- y_end = y + h+boarder
- if y_end > frame1.shape[0]:
- y_end = frame1.shape[0]
-
-
- #crop = frame1[50:100, 1620:1920]
- #print("Shape of the cut", crop.shape)
-
- #If eye thread is not busy, check what is moving
- #TODO If busy for too long do it anyway.
- if not eyes_busy:
- crop = frame[y_start:y_end, x_start:x_end]
- file_name = f"{event_path}{move_frames}.jpg"
- cv2.imwrite(file_name, crop)
- #cv2.imshow("cropped", crop)
- back_log.append(Thread(target = what_is_this, args=[file_name]))
- back_log[-1].setDaemon(True)
- back_log[-1].start()
- else:
- print("Warning, skiping process")
- #Movment but not a triger yet
- else:
- cv2.rectangle(frame1, (x-boarder, y-boarder), (x + w+boarder, y + h+boarder), (255, 0, 0), 2)
-
- #Save frame to video
- print(video_to_save)
- if video_to_save != "":
- video_to_save.write(frame1)
-
- streamer.update_frame(frame1)
- if not streamer.is_streaming:
- streamer.start_streaming()
-
- if found_moving:
- move_frames = move_frames + 1
- else:
- #End of event
- if sleepy_frames > num_frames_needed_to_end_trigger:
- move_frames = 0
- event_path = ""
- sleepy_frames = 0
- if video_to_save != "":
- video_to_save.release()
- video_to_save = ""
- else:
- sleepy_frames = sleepy_frames + 1
-
- cv2.drawContours(frame1,contours,-1,(0,255,255),2)
- #cv2.imshow("inter",frame1)
-
- if cv2.waitKey(40) == 27:
- exit = True
- frame1 = frame2
- ret,frame2= cap.read()
- cv2.destroyAllWindows()
- #VideoFileOutput.release()
- cap.release()
-
-cam_threads = []
-for cap_dev in cam_devices:
- print(f"Starting {cap_dev} {cam_devices[cap_dev]}")
- cam_threads.append(Thread(target=main_cam_loop, args=[cap_dev, cam_devices[cap_dev]]))
- cam_threads[-1].setDaemon(True)
- cam_threads[-1].start()
- time.sleep(3)
-
-def on_exit(signal_received, frame):
- global exit
- exit = True
- # Handle any cleanup here
- print('SIGINT or CTRL-C detected. Exiting gracefully')
-
-signal(SIGINT, on_exit)
-while not exit:
- time.sleep(1)
D security sensors/settings.txt => security sensors/settings.txt +0 -5
@@ 1,5 0,0 @@
-#Name~Device
-Door~rtsp://10.250.10.225:554/Streaming/Channes/ID/?transportmode=unicast
-#Room~0
-#Window~4
-#Shed~2
D security sensors/setup.txt => security sensors/setup.txt +0 -22
@@ 1,22 0,0 @@
-https://github.com/facebookresearch/detectron2/blob/main/INSTALL.md
-sudo pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu113
-sudo python3 -m pip install 'git+https://github.com/facebookresearch/detectron2.git'
-
-#sudo pip3 install cython; pip install -U 'git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI'
-
-#Old
-Install pip2
-#CPU
-sudo pip2 install "tensorflow<2.0"
-sudo pip2 install luminoth
-
-#GPU
-sudo pip2 install "tensorflow-gpu<2.0"
-sudo pip2 install luminoth[tf-gpu]
-
-lumi checkpoint refresh
-lumi checkpoint list
-lumi checkpoint download accurate
-lumi checkpoint download fast
-
-lumi predict --checkpoint=fast <Img>
D security sensors/startup.sh => security sensors/startup.sh +0 -5
@@ 1,5 0,0 @@
-#!/bin/bash
-#Limit memory use
-cd "$(dirname "$0")"
-export LRU_CACHE_CAPACITY=1
-LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 python3 ./sensors.py
D security sensors/templates/fail.html => security sensors/templates/fail.html +0 -15
@@ 1,15 0,0 @@
-<!doctype html>
-<html>
-
-<body>
- <div id="reason" style="display: none;">
- {{reason}}
- </div>
-
- <script>
- alert(document.getElementById("reason").innerText);
- location.href = "../change%20password";
- </script>
-</body>
-
-</html>>
\ No newline at end of file
D security sensors/templates/form.html => security sensors/templates/form.html +0 -33
@@ 1,33 0,0 @@
-<!doctype html>
-<html>
-
-<body>
- <center>
- <form action="../change%20password%20result" method="POST">
- <table>
- <tr>
- <th>Username:</th>
- <th><input type="text" name="username" /></th>
- </tr>
- <tr>
- <th>Old Password</th>
- <th><input type="password" name="old_pw" /></th>
- </tr>
- <tr>
- <th>New Password</th>
- <th><input type="password" name="pw" /></th>
- </tr>
- <tr>
- <th>(Confirm)</th>
- <th><input type="password" name="pw_conf" /></th>
- </tr>
- <tr>
- <th><input type="submit" value="Change Password" /></th>
- <th></th>
- </tr>
- </table>
- </form>
- </center>
-</body>
-
-</html>>
\ No newline at end of file
D security sensors/templates/index.html => security sensors/templates/index.html +0 -9
@@ 1,9 0,0 @@
-<html>
- <head>
- <title>Video Streaming Demonstration</title>
- </head>
- <body>
- <h1>Video Streaming Demonstration</h1>
- <img src="{{ url_for('video_feed') }}">
- </body>
-</html>
D security sensors/templates/pass.html => security sensors/templates/pass.html +0 -15
@@ 1,15 0,0 @@
-<!doctype html>
-<html>
-
-<body>
- <script>
- alert("Sucessfully changed password!");
- location.href = "..";
- </script>
-
- <p>
- {{reason}}
- </p>
-</body>
-
-</html>>
\ No newline at end of file