def __init__(self, name, data):
        devices.Device.__init__(self, name, data)
        try:
            self.runWidgetThread = True
            self.threadExited = True
            self.closed = False
            self.set_config_default("device.storage_dir", '~/NVR')

            self.set_config_default("device.loop_record_length", '5')

            self.process = None

            self.lastInferenceTime = 1

            self.lastDidObjectRecognition = 0

            # So we can tell if there is new object recogintion data since we last checked.
            self.lastDidMotionRecordControl=0

            # Used to detect motion by looking at changes in the number of relevant objects.
            # Response time may be very low.
            self.oldRelevantObjectCount = -1

            # The most recent set of object detection results.
            self.lastObjectSet=None

            # We don't want to stop till a few seconds after an event that would cause motion
            self.lastRecordTrigger = 0

            # We also DO want to stop if we are in object record mode and have not seen the object in a long time

            self.lastObjectDetectionHit = 0

            # If this is true, record when there is motion
            self.set_config_default("device.motion_recording", 'no')

            self.storageDir = os.path.expanduser(
                self.config['device.storage_dir'] or '~/NVR')

            self.segmentDir = None

            # When changing segment dir, we can't do it instantly, we instead wait to be done with the current file.
            self.activeSegmentDir = None

            # How many segments in this dir. Must track so we can switch to a new directory if we need to.
            self.directorySegments = 0

            self.lastshm = None

            self.canAutoStopRecord = False

            if not os.path.exists(self.storageDir):
                os.makedirs(self.storageDir)
                # Secure it!
                os.chmod(self.storageDir, 0o700)

            self.tsQueue = b''

            self.recordlock = threading.RLock()

            self.rawFeedPipe = "/dev/shm/knvr_buffer/" + self.name + "." + str(time.monotonic()) + ".raw_feed.tspipe"

            self.bytestream_data_point("raw_feed",
                                       subtype='mpegts',
                                       writable=False)


            #Give this a little bit of caching
            self.bytestream_data_point("bmp_snapshot",
                                       subtype='bmp',
                                       writable=False,
                                       interval=0.3)

            self.set_data_point_getter('bmp_snapshot', self.getSnapshot)


            self.numeric_data_point("switch",
                                    min=0,
                                    max=1,
                                    subtype='bool',
                                    default=1,
                                    handler=self.commandState)

            self.numeric_data_point("record",
                                    min=0,
                                    max=1,
                                    subtype='bool',
                                    default=0,
                                    handler=self.onRecordingChange)

            self.numeric_data_point("running",
                                    min=0,
                                    max=1,
                                    subtype='bool',
                                    writable=False)

            self.numeric_data_point("motion_detected",
                                    min=0,
                                    max=1,
                                    subtype='bool',
                                    writable=False)

            self.numeric_data_point("raw_motion_value",
                                    min=0,
                                    max=250,
                                    writable=False)

            self.numeric_data_point("luma_average",
                                    min=0,
                                    max=1,
                                    writable=False)

            self.numeric_data_point("luma_variance",
                                    min=0,
                                    max=1,
                                    writable=False)

            self.set_alarm("Camera dark", "luma_average",
                           "value < 0.095", trip_delay=3, auto_ack=True)
            self.set_alarm("Camera low varience", "luma_variance",
                           "value < 0.008", trip_delay=3, auto_ack=True)
            self.set_alarm("Long_recording", "record",
                           "value > 0.5", trip_delay=800, auto_ack=True, priority='debug')

            self.set_alarm("Not Running", "running",
                           "value < 0.5", trip_delay=5, auto_ack=False, priority='warning')

            self.set_config_default("device.source", '')
            self.set_config_default("device.username", '')
            self.set_config_default("device.password", '')


            self.set_config_default("device.fps", '4')
            self.set_config_default("device.barcodes", 'no')
            self.set_config_default("device.object_detection", 'no')

            self.set_config_default("device.object_record", 'person, dog, cat, horse, sheep, cow, handbag, frisbee, bird, backpack, suitcase, sports ball')

            self.set_config_default("device.motion_threshold", '0.08')
            self.set_config_default("device.bitrate", '386')

            self.set_config_default("device.retain_days", '90')

            self.config.pop("device.motion_sensitivity", 0)

            self.retainDays = int(self.config['device.retain_days'])

            if self.config['device.barcodes'].lower() in ('yes', 'true', 'enable', 'enabled'):
                self.object_data_point("barcode",
                                       writable=False)

            if self.config['device.object_detection'].lower() in ('yes', 'true', 'enable', 'enabled'):
                self.object_data_point("detected_objects",
                                       writable=False)

            self.config_properties['device.loop_record_length']={
                'description':'How many seconds to buffer at all times to allow recording things before motion events actually happen.'
            }

            self.config_properties['device.barcodes'] = {
                'type': 'bool'
            }


            self.config_properties['device.object_detection'] = {
                'type': 'bool',
                'description': "Enable object detection.  See kaithem readme for where to put model files. "
            }

            self.config_properties['device.object_record'] = {
                'description': "Does nothing without object detection. Only record if there is both motion, and a recognized object on the list in the frame. If empty, always record. Can use any COCO item."
            }

            self.config_properties['device.source'] = {
                'secret': True
            }

            self.config_properties['device.motion_recording'] = {
                'type': 'bool'
            }

            self.config_properties['device.storage_dir'] = {
                'type': 'local_fs_dir'
            }

            self.streamLock = threading.RLock()
            self.lastStart = 0

            mediaFolders[name] = self

            self.connect(self.config)
            self.set_data_point('switch', 1)

            # Used to check that things are actually still working.
            self.lastSegment = time.monotonic()
            self.lastPushedWSData = time.monotonic()

            self.check()
            from src import scheduling
            self.checker = scheduling.scheduler.every(self.check, 3)

        except Exception:
            self.handleException()