def __Update(self):
    while self.__Running:
      # If we lose our device, stop this thread.
      if self.__CheckTimeout() is False:
        break

      # if we suddenly lose our instance, set an error flag and attempt to get it again
      if self.__cap is None:
        self.__SetError()
        self.__FPSSync()
        continue

      retVal, image  = self.__cap.read()

      if not retVal:
        self.__SetStatus("Encountered frame capture error")
        self.__SetError()
        self.__FPSSync()
        continue
      else:
        DogCamLogger.Log("Webstream: Capturing image", DCLogLevel.Verbose)
        self.__img = cv2.resize(image, (self.resWidth, self.resHeight))
        if self.__LastErrorTime > 0.0:
          DogCamLogger.Log("Webstream: Recovered from net disruption")
          self.__SetStatus("Recovered from net disruption")
          self.__LastErrorTime = 0.0

      self.__FPSSync()
    def CreateAI(aiType,
                 aiModel,
                 boundsXSize=10,
                 boundsYSize=10,
                 minimumConfidence=0.3,
                 displayOut=False,
                 detectionID=0,
                 logMatches=False,
                 throttleTilt=False,
                 tiltCooldown=0.75):
        NewAIClass = None

        DogCamLogger.Log(f"AI: Using model file {aiModel}", DCLogLevel.Verbose)

        if not path.exists(aiModel):
            DogCamLogger.Log(f"AI: Given model file {aiModel} does not exist!",
                             DCLogLevel.Error)
            return None

        className = aiType
        if className == "tf":
            NewAIClass = DogCamAITFLite(aiModel)
        elif className == "dnn":
            NewAIClass = DogCamAIDNN(aiModel)

        if NewAIClass is not None:
            NewAIClass.Initialize(boundsXSize, boundsYSize, minimumConfidence,
                                  displayOut, detectionID, logMatches,
                                  throttleTilt, tiltCooldown)
        else:
            DogCamLogger.Log(
                f"AI: Could not create class of type {className}! Fatal error!",
                DCLogLevel.Error)

        return NewAIClass
  def Open(self):
    DogCamLogger.Log("Webstream: Loading video feed", DCLogLevel.Notice)
    if self.__cap is not None:
      DogCamLogger.Log("Webstream: Another capture instance already exists", DCLogLevel.Warn)

    self.__LastConnectionAttempt = time.time()
    self.__cap = cv2.VideoCapture(self.vidURL)

    # Keep only a few frames in the buffer, dropping dead frames
    self.__cap.set(cv2.CAP_PROP_BUFFERSIZE, self.fbSize)

    if not self.__cap.isOpened():
      DogCamLogger.Log("Webstream: Could not capture the video!", DCLogLevel.Warn)
      self.__SetStatus("Failed to load video capture")
      self.__cap = None
      return False
    else:
      self.__SetStatus("Video feed loaded")

    if self.resWidth == 0:
      self.resWidth = self.__cap.get(cv2.CAP_PROP_FRAME_WIDTH)
    if self.resHeight == 0:
      self.resHeight = self.__cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
    
    self.__LastErrorTime = 0.0
    return True
  def Start(self):
    # if we already have a running instance, don't start it again
    if self.__cap is not None:
      return True
    
    if self.Open():
      DogCamLogger.Log("Webstream: Starting thread")
      self.__Running = True
      self.__thread = threading.Thread(target=self.__Update, daemon=True)
      self.__thread.start()
      return True
    else:
      DogCamLogger.Log("Webstream: Failed to start!", DCLogLevel.Warn)
      self.Stop()

    return False
 def __SetError(self):
   # If we already have a pending error time, then we're already handling this issue somewhere else
   if self.__LastErrorTime <= 1.0:
     DogCamLogger.Log("Webstream: Detected error, waiting...", DCLogLevel.Error)
     self.__LastErrorTime = time.time()
     self.__BlankImage()
     self.__ReleaseCapture()
Exemple #6
0
    def __MessageThread(self):
        while self.__processing:

            # Attempt to handle reconnection
            if self.IsConnectionReady() is False:

                # Handle timeouts
                if self.__reconnectTimeout == 0.0:
                    DogCamLogger.Log("Websocket: Detected disconnection",
                                     DCLogLevel.Warn)
                    self.__reconnectTimeout = time.time()
                    self.__reconnect = True
                elif (time.time() -
                      self.__reconnectTimeout) >= self.__maxTimeout:
                    DogCamLogger.Log(
                        "Websocket: Exhausted retries to reconnect",
                        DCLogLevel.Error)
                    self.__processing = False
                    break

                if self.__reconnect is True:
                    self.Connect()

                time.sleep(2)
                continue

            try:
                Message = self.__socket.recv()
                if not Message:
                    time.sleep(1)
                    continue

                DogCamLogger.Log(f"Websocket: Got message: {Message}",
                                 DCLogLevel.Debug)

            except (websocket.WebSocketConnectionClosedException,
                    BrokenPipeError):
                DogCamLogger.Log("Websocket: was disconnected!",
                                 DCLogLevel.Warn)
                self.__socket = None
                continue
            except KeyboardInterrupt:
                break

            time.sleep(0.5)
Exemple #7
0
    def SendMessage(self, message):
        if message is None or self.IsConnectionReady() is False:
            return

        try:
            self.__socket.send(message)
        except Exception as ex:
            DogCamLogger.Log(
                f"Websocket: Failed to send message {message}!\nException: {ex}",
                DCLogLevel.Warn)
Exemple #8
0
    def Connect(self):
        self.__reconnect = False
        try:
            self.__socket.close()
            self.__socket = None
        except:
            DogCamLogger.Log("Websocket: Socket constructing")

        try:
            self.__socket = websocket.WebSocket()
            self.__socket.connect(self.URL)
            DogCamLogger.Log("Websocket: Socket connected!", DCLogLevel.Notice)
            self.__OnConnected()
        except KeyboardInterrupt:
            DogCamLogger.Log("Websocket: Interrupted!", DCLogLevel.Debug)
            raise
        except Exception as ex:
            DogCamLogger.Log(f"Websocket: Failed to connect!\nException: {ex}",
                             DCLogLevel.Warn)
            self.__socket = None
            self.__reconnect = True
  def __CheckTimeout(self):
    lastConnectionAttempt = (time.time() - self.__LastConnectionAttempt)
    
    isTotalDisconnection = (time.time() - self.__LastErrorTime) >= self.netTimeout and self.__LastErrorTime > 0.0
    isConnectionRetry = (self.__cap is None or self.__cap.isOpened() is False) and lastConnectionAttempt >= 5.0

    # See if we should check to restart the capture software again
    if isTotalDisconnection:
      # At this point we are starved of updates entirely and we fail out.
      DogCamLogger.Log("Webstream: Timeout has occurred!", DCLogLevel.Notice)
      self.__SetStatus("Total timeout has occurred! Stopping video capture service")
      self.__Running = False
      self.__ReleaseCapture()
      self.__BlankImage()
      return False
    elif isConnectionRetry:
      DogCamLogger.Log("Webstream: Attempting to restart capture", DCLogLevel.Log)
      self.__SetStatus(f"Attempting to restart capture at {lastConnectionAttempt} of max time {self.netTimeout}")
      self.__BlankImage()
      self.__ReleaseCapture()
      self.Open()
      time.sleep(1)

    return True
    def __ProcessImage(self):
        # Unlikely, but we'll be safe anyways
        if self._image is None:
            DogCamLogger.Log("AI: Skipping blank image", DCLogLevel.Debug)
            return

        ProcessingTime = time.time()

        # Handle tilt throttling
        if (ProcessingTime - self._LastTiltMoveTime) > self._TiltMoveCooldown:
            self._blockTiltMove = False

        DogCamLogger.Log(f"AI: Processing image at {ProcessingTime}!",
                         DCLogLevel.Verbose)

        self._ProcessImageInternal()

        ProcessingTime = time.time() - ProcessingTime
        if self.debugDisplay:
            DogCamLogger.Log("AI: Displaying image", DCLogLevel.Debug)
            cv2.imshow("Output", self._image)

        DogCamLogger.Log(f"AI: Image processed in {ProcessingTime} seconds",
                         DCLogLevel.Verbose)
    def Initialize(self,
                   boundsXSize=10,
                   boundsYSize=10,
                   minimumConfidence=0.3,
                   displayOut=False,
                   detectionID=0,
                   logMatches=False,
                   throttleTilt=False,
                   tiltCooldown=0.75):

        self.debugDisplay = displayOut
        self._boundsX = int(boundsXSize)
        self._boundsY = int(boundsYSize)
        self._minConfidence = float(minimumConfidence)
        self._image = None
        self._logMatches = logMatches
        self.__pendingImage = None
        self._targetID = detectionID
        self._ThrottleTiltMovement = throttleTilt
        self._TiltMoveCooldown = tiltCooldown

        self._thread = threading.Thread(target=self.__Update)
        DogCamLogger.Log("AI: Initialized", DCLogLevel.Debug)
 def _LogObjectFound(self, objectID, confidence):
     if confidence >= self._minConfidence and self._logMatches is True:
         DogCamLogger.Log(
             f"AI: Found object {objectID} with confidence {confidence}")
 def __init__(self):
   with open("./config.json","r") as cfg_file:
     ConfigData = json.load(cfg_file)
     self.__dict__ = ConfigData
     DogCamLogger.SetLogLevel(self.LoggingLevel)
     DogCamLogger.Log("Config data has been loaded!", DCLogLevel.Notice)
 def __BlankImage(self):
   DogCamLogger.Log("Webstream: Blanking image", DCLogLevel.Debug)
   self.__img = None
    def PushImage(self, image):
        if image is None:
            DogCamLogger.Log("AI: Image pushed was empty", DCLogLevel.Debug)
            return

        self.__pendingImage = image
 def SetDimensions(self, W, H):
     self._width = int(W)
     self._height = int(H)
     DogCamLogger.Log(f"AI: Resolution is {self._width}x{self._height}")
 def __init__(self):
     DogCamLogger.Log("AI: Allocated", DCLogLevel.Verbose)
Exemple #18
0
from dogcamstreamer import DogCamStreamer
from dogcamaifactory import DogCamAIFactory
from dogcamsocket import DogCamSocket
from dogcamconfig import DogCamConfig
from dogcamlogger import DogCamLogger, DCLogLevel
from pathlib import Path
import time
import os

# Remove any handles before we start
if os.path.exists('exit_handle'):
    os.remove('exit_handle')

# Start AI stuff
DogCamLogger.Start()
DogCamLogger.Log("Starting classes", DCLogLevel.Notice)

exit_handle = Path('exit_handle')

dcc = DogCamConfig()

aiUsed = dcc.AIMethod.lower()

dcai = DogCamAIFactory.CreateAI(aiType=aiUsed,
                                aiModel=dcc.AIModels[aiUsed],
                                boundsXSize=dcc.AIBoundsXSize,
                                boundsYSize=dcc.AIBoundsYSize,
                                minimumConfidence=dcc.AIMinimumConfidence,
                                displayOut=dcc.AIDisplayVision,
                                detectionID=dcc.AIDetectID,
                                logMatches=dcc.AILogMatches,
 def Stop(self):
     if self._runningThread:
         DogCamLogger.Log("AI: AI Processing Halted", DCLogLevel.Warn)
         self._runningThread = False
         self._thread.join()
 def Start(self):
     DogCamLogger.Log("AI: AI Processing Started", DCLogLevel.Notice)
     self._runningThread = True
     self._thread.start()
 def __SetStatus(self, message):
   DogCamLogger.Log(f"Webstream: set debug string to {message}", DCLogLevel.Debug)
   self.__CurrentStatus = f"AI Stream: {message}"