<commit_before>#!/usr/bin/python
# Based on the "security camera" example Python script found on Linphone.org here:
# https://wiki.linphone.org/wiki/index.php/Raspberrypi:start
# Heavily modified to add motion detector features for Zilog ePIR SBC with ZDots. This is an advanced
# version and I cannot find this exact model, so I think it's discontinued. Should work with minor 
# modifications (and removal of features?) on other motion detectors.
#
# Please let me know if you have questions.
# Author: <NAME> - <EMAIL> dot <EMAIL>

import datetime
import picamera
import linphone
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage
import RPi.GPIO as GPIO
import io
import logging
import serial
import signal
import time
import smtplib
import sys

# Constants 
global thisDeviceName
thisDeviceName = "rpi01"
emailAddressFrom = 'yourEmailFromAddress'
emailAddressTo = 'yourEmailToAddress'
emailSubject = 'Motion detected on camera %s' % (thisDeviceName, )
emailTextAlternate = 'Motion was detected. An image is included in the alternate MIME of this email.'
sipUserName='yourSipUserName'
sipPassword='<PASSWORD>'
sipWhiteList=['sip:<EMAIL>']
detectMotion = True  # Whether or not we have the motion detector SBC connected. True = connected.
ACK =  6 # "Acknowledge" character
NACK = 21 # "Non-Acknowledge" character

# *** WARNING *** Do not change these unless you are SURE what you are doing! ***
LEDPIN = 11  # Status - could do without
MDPIN = 15  # Motion Detected pin

# These can be changed, but beware of setting them too low because camera IO takes place during both
# motion detection and sending email phases:
WAITSECONDS = 20  # Set to zero to send a message every time motion is detected.
									# WAITSECONDS also controls the shortest amount of time between printing "Motiono detected".
WAITEMAILSECONDS = 20  # How long to wait between sending emails. Independent of WAITSECONDS.
#WAITEMAILSECONDS = 60  # How long to wait between sending emails. Independent of WAITSECONDS. I recommend 60 or more, but use what you want.

#global debug
#debug = True

def readLineCR(port):
  s = ''
  while  True:
    try:
      ch = port.read(1)
      s += ch
      if ch == '\r' or ch == '':
        break
    except: # TODO: Add specific exceptions here.
      pass # Will be a "ready to read, but no data", in my experience.
  return s
 
class SecurityCamera:
  def __init__(self, username='', password='', whitelist=[], camera='', snd_capture='', snd_playback=''):
    #if debug:
    #print "setting audio_dscp"
    # Pulling my values from "Commonly used DSCP Values" table in this article: 
    # https://en.wikipedia.org/wiki/Differentiated_services
    #self.core.audio_dscp = 26 
    #self.core.video_dscp = 46 # 46 = High Priority Expedited Forwarding (EF) - TODO: Can this be lowered???
    
    self.lastMessageTicks = time.time() - (WAITSECONDS / 2)
    self.lastEmailTicks = time.time() - (WAITEMAILSECONDS / 2)
    #self.camera = self.core.video_device

    # Initialize email
    self.smtp = smtplib.SMTP()
    #self.smtp.connect('smtp.gmail.com', 587)
    #self.smtp.starttls() # TODO: Can this be moved out of the iteration? Is it expensive?
    
    # Initialize the motion detector. This is for the Zilog ePIR ZDot SBC. It has more features via serial mode,
    # so that's what we'll use here. 
    GPIO.setwarnings(False) # Disable "this channel already in use", etc.    
    
    GPIO.setmode(GPIO.BOARD)
    self.port = serial.Serial("/dev/ttyAMA0", baudrate = 9600, timeout = 2)
    
    # let the ePIR sensor wake up.
    #time.sleep(10) # Arduino example says need delays between commands for proper operation. (I suspect for 9600 bps it needs time.)
    time.sleep(5)
    ch = 'U'
    while ch == 'U': # Repeat loop if not stablized. (ePIR replies with the character 'U' until the device becomes stable) 
      time.sleep(1)
      ch = self.port.read(1) # Sends status command to ePIR and assigns reply from ePIR to variable ch. (READ ONLY function)
      #if debug:
      print 'ch = %s' % (ch, )
    #time.sleep(1)  
    #ch = readLine(self.port)
    #if debug:
    
    self.port.write('CM');
    time.sleep(3) # If we don't do this, the next line will get garbage and will take an indermined amount of time!
    result = readLineCR(self.port)
    
    #if debug:
    if result == 'R':
      print 'ePIR reset!'
    elif result == 'M':
      print 'Motion detection mode confirmed.'
    else:
      print 'Result = "%s"' % (result, )
  
    GPIO.setup(LEDPIN, GPIO.OUT) # Light (blink?) when motion detected
    GPIO.setup(MDPIN, GPIO.IN)

    print "ch = '%s'\r\nDevice Ready" % (ch, )
    
    # Other member variables:
    self.imgStream = io.BytesIO()
    #time.sleep(2) #Allow time for ePIR warming-up
    
    self.quit = False
    self.whitelist = whitelist
    callbacks = {
      'call_state_changed': self.call_state_changed,
    }
    print "__init__"
    
    # Initialize & Configure the linphone core
    logging.basicConfig(level=logging.INFO)
    signal.signal(signal.SIGINT, self.signal_handler)
    linphone.set_log_handler(self.log_handler)
    self.core = linphone.Core.new(callbacks, None, None)
    self.core.max_calls = 1
    self.core.echo_cancellation_enabled = False
    self.core.video_capture_enabled = True
    self.core.video_display_enabled = False
    self.core.stun_server = 'stun.linphone.org'
    self.core.firewall_policy = linphone.FirewallPolicy.PolicyUseIce
    if len(camera):
      self.core.video_device = camera
    if len(snd_capture):
      self.core.capture_device = snd_capture
    if len(snd_playback):
      self.core.playback_device = snd_playback
 <commit_msg>Small fixes and many changes and enhancements<commit_after>#!/usr/bin/python
# Based on the "security camera" example Python script found on Linphone.org here:
# https://wiki.linphone.org/wiki/index.php/Raspberrypi:start
# Heavily modified to add motion detector features for Zilog ePIR SBC with ZDots. This is an advanced
# version and I cannot find this exact model, so I think it's discontinued. Should work with minor 
# modifications (and removal of features?) on other motion detectors.
#
# Please let me know if you have questions.
# Author: <NAME> - aboogieman at gmail dot com

import datetime
import picamera
import linphone
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage
import RPi.GPIO as GPIO
import io
import logging
import serial
import signal
import time
import smtplib
import sys

# Constants 
global thisDeviceName
thisDeviceName = "rpi01"
emailAddressFrom = 'yourEmailFromAddress'
emailAddressTo = 'yourEmailToAddress'
emailSubject = 'Motion detected on camera %s' % (thisDeviceName, )
emailTextAlternate = 'Motion was detected. An image is included in the alternate MIME of this email.'
sipUserName='yourSipUserName'
sipPassword='<PASSWORD>'
sipWhiteList=['sip:<EMAIL>']
detectMotion = True  # Whether or not we have the motion detector SBC connected. True = connected.
ACK =  6 # "Acknowledge" character
NACK = 21 # "Non-Acknowledge" character

# *** WARNING *** Do not change these unless you are SURE what you are doing! ***
LEDPIN = 11  # Status - could do without
MDPIN = 15  # Motion Detected pin

# These can be changed, but beware of setting them too low because camera IO takes place during both
# motion detection and sending email phases:
WAITSECONDS = 20  # Set to zero to send a message every time motion is detected.
									# WAITSECONDS also controls the shortest amount of time between printing "Motiono detected".
#WAITEMAILSECONDS = 20  # How long to wait between sending emails. Independent of WAITSECONDS.
WAITEMAILSECONDS = 60  # How long to wait between sending emails. Independent of WAITSECONDS. I recommend 60 or more, but use what you want.

#global debug
#debug = True

def readLineCR(port):
  s = ''
  while  True:
    try:
      ch = port.read(1)
      s += ch
      if ch == '\r' or ch == '':
        break
    except: # TODO: Add specific exceptions here.
      pass # Will be a "ready to read, but no data", in my experience.
  return s
 
class SecurityCamera:
  def __init__(self, username='', password='', whitelist=[], camera='', snd_capture='', snd_playback=''):
    #if debug:
    #print "setting audio_dscp"
    # Pulling my values from "Commonly used DSCP Values" table in this article: 
    # https://en.wikipedia.org/wiki/Differentiated_services
    #self.core.audio_dscp = 26 
    #self.core.video_dscp = 46 # 46 = High Priority Expedited Forwarding (EF) - TODO: Can this be lowered???
    
    self.lastMessageTicks = time.time() - (WAITSECONDS / 2)
    self.lastEmailTicks = time.time() - (WAITEMAILSECONDS / 2)
    #self.camera = self.core.video_device

    # Initialize email
    self.smtp = smtplib.SMTP()
    #self.smtp.connect('smtp.gmail.com', 587)
    #self.smtp.starttls() # TODO: Can this be moved out of the iteration? Is it expensive?
    
    # Initialize the motion detector. This is for the Zilog ePIR ZDot SBC. It has more features via serial mode,
    # so that's what we'll use here. 
    GPIO.setwarnings(False) # Disable "this channel already in use", etc.    
    
    GPIO.setmode(GPIO.BOARD)
    self.port = serial.Serial("/dev/ttyAMA0", baudrate = 9600, timeout = 2)
    
    # let the ePIR sensor wake up.
    #time.sleep(10) # Arduino example says need delays between commands for proper operation. (I suspect for 9600 bps it needs time.)
    time.sleep(5)
    ch = 'U'
    while ch == 'U': # Repeat loop if not stablized. (ePIR replies with the character 'U' until the device becomes stable) 
      time.sleep(1)
      ch = self.port.read(1) # Sends status command to ePIR and assigns reply from ePIR to variable ch. (READ ONLY function)
      #if debug:
      print 'ch = %s' % (ch, )
    #time.sleep(1)  
    #ch = readLine(self.port)
    #if debug:
    
    self.port.write('CM');
    time.sleep(3) # If we don't do this, the next line will get garbage and will take an indermined amount of time!
    result = readLineCR(self.port)
    
    #if debug:
    if result == 'R':
      print 'ePIR reset!'
    elif result == 'M':
      print 'Motion detection mode confirmed.'
    else:
      print 'Result = "%s"' % (result, )
  
    GPIO.setup(LEDPIN, GPIO.OUT) # Light (blink?) when motion detected
    GPIO.setup(MDPIN, GPIO.IN)

    print "ePIR device ready"
    
    # Other member variables:
    self.imgStream = io.BytesIO()
    #time.sleep(2) #Allow time for ePIR warming-up
    
    self.quit = False
    self.whitelist = whitelist
    callbacks = {
      'call_state_changed': self.call_state_changed,
    }
    print "__init__"
    
    # Initialize & Configure the linphone core
    logging.basicConfig(level=logging.INFO)
    signal.signal(signal.SIGINT, self.signal_handler)
    linphone.set_log_handler(self.log_handler)
    self.core = linphone.Core.new(callbacks, None, None)
    self.core.max_calls = 1
    self.core.echo_cancellation_enabled = False
    self.core.video_capture_enabled = True
    self.core.video_display_enabled = False
    self.core.stun_server = 'stun.linphone.org'
    self.core.firewall_policy = linphone.FirewallPolicy.PolicyUseIce
    if len(camera):
      self.core.video_device = camera
    if len(snd_capture):
      self.core.capture_device = snd_capture
    if len(snd_playback):
      self.core.playback_device = snd_playback
 
{'fraction_non_alphanumeric': 0.09482231729677813, 'fraction_numerical': 0.008382083296952763, 'mean_word_length': 3.380114722753346, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2085081', 'n_tokens_mistral': 3722, 'n_tokens_neox': 3547, 'n_words': 1239}