mise à jour du code
This commit is contained in:
+277
-77
@@ -12,32 +12,72 @@ import sys, os, re
|
|||||||
import serial
|
import serial
|
||||||
import logging as log
|
import logging as log
|
||||||
import time
|
import time
|
||||||
|
import RPi.GPIO as GPIO
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
import calendar
|
import calendar
|
||||||
import json
|
import json
|
||||||
|
import socket
|
||||||
|
from signal import signal, SIGINT
|
||||||
|
from threading import Thread
|
||||||
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
# Class et Methods #
|
# Class et Methods #
|
||||||
|
|
||||||
def send_at_cmd(cmd='', serObj=None, log=None):
|
def get_conf(logger=None):
|
||||||
|
''' Get configuration
|
||||||
|
|
||||||
|
:return dict:
|
||||||
|
Configuration dictionnary
|
||||||
|
'''
|
||||||
|
config = None
|
||||||
|
try:
|
||||||
|
with open(os.path.join("/home/pi/KineIntercom/src", "KineIntercom.json"), 'r') as f:
|
||||||
|
try:
|
||||||
|
config = json.load(f)
|
||||||
|
except json.decoder.JSONDecodeError as e:
|
||||||
|
logger.error("Impossible de charger les données de configuration ({})".format(e))
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
logger.error("Impossible d'ouvrir le fichier de configuation ({})".format(e))
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
def send_at_cmd(cmd='', timeout=0.0, serObj=None, logger=None):
|
||||||
''' send AT to command to GNSS_HAT
|
''' send AT to command to GNSS_HAT
|
||||||
|
|
||||||
:param cmd:
|
:param cmd:
|
||||||
string AT command
|
string AT command
|
||||||
|
|
||||||
|
:param timeout:
|
||||||
|
float timeout to read response
|
||||||
|
|
||||||
:param serObj:
|
:param serObj:
|
||||||
serial object
|
serial object
|
||||||
|
|
||||||
:param log:
|
:param log:
|
||||||
logger object
|
logger object
|
||||||
|
|
||||||
:return bool:
|
:return int:
|
||||||
True if ok, False otherwise
|
0 if ok, 2 if error, otherwise 1
|
||||||
'''
|
'''
|
||||||
if not isinstance(cmd, str):
|
if not isinstance(cmd, str):
|
||||||
log.error("error parameter, expecting str, get {}".format(type(cmd)))
|
logger.error("error parameter, expecting str, get {}".format(type(cmd)))
|
||||||
return False
|
return 2
|
||||||
|
if not isinstance(timeout, float):
|
||||||
|
logger.error("error parameter, expecting float, get {}".format(type(timeout)))
|
||||||
|
return 2
|
||||||
|
if not isinstance(serObj, serial.serialposix.Serial):
|
||||||
|
logger.error("error parameter, expecting serial.serialposix.Serial, get {}".format(type(serObj)))
|
||||||
|
return 2
|
||||||
|
if not isinstance(logger, log.Logger):
|
||||||
|
logger.error("error parameter, expecting logging.Logger, get {}".format(type(log)))
|
||||||
|
return 2
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if timeout > 0:
|
||||||
|
serObj.timeout = timeout
|
||||||
|
else:
|
||||||
|
serObj.timeout = None
|
||||||
serObj.write(bytes(cmd+'\r', 'utf-8'))
|
serObj.write(bytes(cmd+'\r', 'utf-8'))
|
||||||
time.sleep(.5)
|
time.sleep(.5)
|
||||||
out = ''
|
out = ''
|
||||||
@@ -50,18 +90,20 @@ def send_at_cmd(cmd='', serObj=None, log=None):
|
|||||||
out = ''
|
out = ''
|
||||||
else:
|
else:
|
||||||
out += c
|
out += c
|
||||||
log.debug("Reponse: {}".format(outlst))
|
logger.debug("Reponse: {}".format(outlst))
|
||||||
if 'OK' in outlst:
|
if 'OK' in outlst:
|
||||||
return True
|
return 0
|
||||||
elif 'ERROR' in outlst:
|
elif 'ERROR' in outlst:
|
||||||
log.error("Error with cmd : {}".format(cmd))
|
logger.error("Error with cmd : {}".format(cmd))
|
||||||
return False
|
return 2
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error("Error: {}".format(e))
|
logger.error("Error: {}".format(e))
|
||||||
return False
|
return 2
|
||||||
return True
|
return 0
|
||||||
|
|
||||||
def init_com(serObj=None, config=None, log=None):
|
def init_gsm_com(serObj=None, config=None, logger=None):
|
||||||
''' Init GSM Communication
|
''' Init GSM Communication
|
||||||
source : SIM800_Series_AT_command Manual_v1.09
|
source : SIM800_Series_AT_command Manual_v1.09
|
||||||
AT : test command
|
AT : test command
|
||||||
@@ -87,6 +129,13 @@ def init_com(serObj=None, config=None, log=None):
|
|||||||
|
|
||||||
:return bool:
|
:return bool:
|
||||||
'''
|
'''
|
||||||
|
if not isinstance(serObj, serial.serialposix.Serial):
|
||||||
|
logger.error("error parameter, expecting serial.serialposix.Serial, get {}".format(type(serObj)))
|
||||||
|
return False
|
||||||
|
if not isinstance(logger, log.Logger):
|
||||||
|
logger.error("error parameter, expecting logging.Logger, get {}".format(type(log)))
|
||||||
|
return False
|
||||||
|
|
||||||
cmd_lst = ['AT',
|
cmd_lst = ['AT',
|
||||||
'ATE1',
|
'ATE1',
|
||||||
'AT+CMEE=2',
|
'AT+CMEE=2',
|
||||||
@@ -97,11 +146,12 @@ def init_com(serObj=None, config=None, log=None):
|
|||||||
'AT+CLIP=1',
|
'AT+CLIP=1',
|
||||||
'AT+VTD='+str(config['DTMF_DURATION'])]
|
'AT+VTD='+str(config['DTMF_DURATION'])]
|
||||||
for cmd in cmd_lst:
|
for cmd in cmd_lst:
|
||||||
ret = send_at_cmd(cmd=cmd, serObj=serObj, log=log)
|
ret = send_at_cmd(cmd=cmd, timeout=0.0, serObj=serObj, logger=logger)
|
||||||
if not ret:
|
if ret == 2:
|
||||||
logger.warning("fermeture du port de communication avec le GNSS_HAT")
|
logger.error("Erreur avec la commande AT: {}".format(cmd))
|
||||||
serObj.close()
|
|
||||||
return False
|
return False
|
||||||
|
elif ret == 1:
|
||||||
|
lgger.warning("Timeout avec la commande AT: {}".format(cmd))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def verify_caller(buf="", num="", log=None):
|
def verify_caller(buf="", num="", log=None):
|
||||||
@@ -129,8 +179,31 @@ def verify_caller(buf="", num="", log=None):
|
|||||||
return False, phone_number
|
return False, phone_number
|
||||||
return True, phone_number
|
return True, phone_number
|
||||||
|
|
||||||
def verify_open_hours(conf=None, log=None):
|
def listener(sock, logger):
|
||||||
|
''' Thread socket listener
|
||||||
'''
|
'''
|
||||||
|
logger.debug("Démarrage du serveur de communication avec le service horaire")
|
||||||
|
while True:
|
||||||
|
# Wait for a connection
|
||||||
|
try:
|
||||||
|
clientsocket, address = sock.accept()
|
||||||
|
except socket.timeout:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# socket recv() will block for a maximum of 1 sec.
|
||||||
|
#clientsocket.settimeout(1)
|
||||||
|
while clientsocket:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = clientsocket.recv(1)
|
||||||
|
except Error as e:
|
||||||
|
continue
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
|
||||||
|
def verify_open_hours(conf=None, log=None):
|
||||||
|
''' Verify if GSM HAT must be opened with conf hours
|
||||||
|
|
||||||
:param conf:
|
:param conf:
|
||||||
configuration object
|
configuration object
|
||||||
|
|
||||||
@@ -140,19 +213,72 @@ def verify_open_hours(conf=None, log=None):
|
|||||||
:return bool:
|
:return bool:
|
||||||
True if authorized, False otherwise
|
True if authorized, False otherwise
|
||||||
'''
|
'''
|
||||||
|
flag = False
|
||||||
my_date = date.today()
|
my_date = date.today()
|
||||||
day = calendar.day_name[my_date.weekday()]
|
day = calendar.day_name[my_date.weekday()]
|
||||||
log.debug("Current day is {}".format(day))
|
|
||||||
log.debug("CONF {}".format(conf[day]))
|
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
current_time = now.strftime("%Hh%M")
|
for k,v in conf[day].items():
|
||||||
log.debug("current time : {}".format(current_time))
|
time_conf = int(k.split('h')[0])*60 + int(k.split('h')[1])
|
||||||
return True
|
current_time = now.hour*60 + now.minute
|
||||||
|
if current_time >= time_conf:
|
||||||
|
if v == 1:
|
||||||
|
flag = True
|
||||||
|
elif v == 0:
|
||||||
|
flag = False
|
||||||
|
log.debug('Jour: {} - Temps courant: {} - Ouverture: {}'.format(day, now.strftime('%Hh%M'), flag))
|
||||||
|
return flag
|
||||||
|
|
||||||
|
def init_module():
|
||||||
|
''' initialisation of GNSS/GPS/GSM HAT Module
|
||||||
|
'''
|
||||||
|
GPIO.setwarnings(False)
|
||||||
|
GPIO.setmode(GPIO.BOARD)
|
||||||
|
GPIO.setup(7, GPIO.OUT)
|
||||||
|
return
|
||||||
|
|
||||||
|
def setup_module():
|
||||||
|
''' Setup module (Set/Reset)
|
||||||
|
'''
|
||||||
|
while True:
|
||||||
|
GPIO.output(7, GPIO.LOW)
|
||||||
|
time.sleep(2)
|
||||||
|
GPIO.output(7, GPIO.HIGH)
|
||||||
|
break
|
||||||
|
GPIO.cleanup()
|
||||||
|
|
||||||
|
def cron_verify_hours(config=None, logger=None):
|
||||||
|
''' cron task
|
||||||
|
'''
|
||||||
|
global GSM_MODULE_STATE
|
||||||
|
# Verify hours with conf file
|
||||||
|
opened = verify_open_hours(conf=config, log=logger)
|
||||||
|
if opened:
|
||||||
|
# Si le module GSM doit être allumé et qu'il est éteint, on l'allume
|
||||||
|
if not GSM_MODULE_STATE:
|
||||||
|
logger.info("Allumage du module GSM HAT ...")
|
||||||
|
setup_module()
|
||||||
|
GSM_MODULE_STATE = True
|
||||||
|
else:
|
||||||
|
# Si le module GSM doit être éteint et qu'il est allumé, on l'eteint
|
||||||
|
if GSM_MODULE_STATE:
|
||||||
|
logger.debug("Fermeture du module GSM HAT ...")
|
||||||
|
setup_module()
|
||||||
|
GSM_MODULE_STATE = False
|
||||||
|
|
||||||
|
def sigint_handler(signal, frame):
|
||||||
|
''' SIGINT handler function
|
||||||
|
'''
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
# Corps principal du programme #
|
# Corps principal du programme #
|
||||||
|
|
||||||
|
GSM_MODULE_STATE = False
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
''' main function
|
||||||
|
'''
|
||||||
|
# Logger configuration
|
||||||
logger = log.getLogger("Intercom")
|
logger = log.getLogger("Intercom")
|
||||||
logger.setLevel(log.DEBUG)
|
logger.setLevel(log.DEBUG)
|
||||||
fl = log.StreamHandler()
|
fl = log.StreamHandler()
|
||||||
@@ -161,18 +287,22 @@ def main():
|
|||||||
fl.setFormatter(formatter)
|
fl.setFormatter(formatter)
|
||||||
logger.addHandler(fl)
|
logger.addHandler(fl)
|
||||||
|
|
||||||
config = None
|
global GSM_MODULE_STATE
|
||||||
try:
|
|
||||||
with open(os.path.join("/home/pi/KineIntercom/src", "KineIntercom.json"), 'r') as f:
|
# Caught Keyboard interrupt
|
||||||
try:
|
signal(SIGINT, sigint_handler)
|
||||||
config = json.load(f)
|
|
||||||
except json.decoder.JSONDecodeError as e:
|
# Configuration loader
|
||||||
logger.error("Impossible de charger les données de configuration ({})".format(e))
|
config = get_conf(logger)
|
||||||
exit(1)
|
if not config:
|
||||||
except FileNotFoundError as e:
|
logger.error("Impossible de charger la configuration")
|
||||||
logger.error("Impossible d'ouvrir le fichier de configuation ({})".format(e))
|
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
# init GSM HAT module
|
||||||
|
logger.info("Initialisation du module GSM HAT ...")
|
||||||
|
init_module()
|
||||||
|
|
||||||
|
# Serial configuration
|
||||||
ser = serial.Serial('/dev/ttyAMA0',
|
ser = serial.Serial('/dev/ttyAMA0',
|
||||||
baudrate=115200,
|
baudrate=115200,
|
||||||
parity=serial.PARITY_NONE,
|
parity=serial.PARITY_NONE,
|
||||||
@@ -183,59 +313,129 @@ def main():
|
|||||||
rtscts=False,
|
rtscts=False,
|
||||||
dsrdtr=False)
|
dsrdtr=False)
|
||||||
|
|
||||||
# Verify date and time
|
# Test si le port série est ouvert
|
||||||
ret = verify_open_hours(conf=config['HORAIRES'], log=logger)
|
|
||||||
exit(0)
|
|
||||||
|
|
||||||
if ser.isOpen():
|
if ser.isOpen():
|
||||||
logger.info("Le port de communication avec le GNSS_HAT est ouvert")
|
logger.info("Le port série avec le module GSM est ouvert")
|
||||||
try:
|
try:
|
||||||
ser.flushInput() #flush input buffer, discarding all its contents
|
ser.flushInput() #flush input buffer, discarding all its contents
|
||||||
ser.flushOutput() #flush output buffer, aborting current output
|
ser.flushOutput() #flush output buffer, aborting current output
|
||||||
# Initialize GSM communication
|
ret = send_at_cmd(cmd='AT', timeout=0.5, serObj=ser, logger=logger)
|
||||||
ret = init_com(serObj=ser, config=config, log=logger)
|
if ret == 2:
|
||||||
if not ret:
|
logger.error("Erreur d'envoie de la commande AT")
|
||||||
logger.error("Erreur d'initialisation de la communication avec le module GSM")
|
elif ret == 1:
|
||||||
return
|
logger.warning("Pas de réponse du module GSM")
|
||||||
out = ''
|
GSM_MODULE_STATE = False
|
||||||
while True:
|
else:
|
||||||
# While the number of bytes in the input buffer > 0
|
logger.info("Module GSM HAT allumé ...")
|
||||||
while ser.in_waiting > 0:
|
GSM_MODULE_STATE = True
|
||||||
# remove \r and \n chars from out string
|
|
||||||
out += ser.read_until().decode('utf-8').replace('\r','').replace('\n','')
|
|
||||||
if len(out) > 0 :
|
|
||||||
logger.debug("out: {}".format(out))
|
|
||||||
time.sleep(.1)
|
|
||||||
if out.startswith('+CLIP: '):
|
|
||||||
# Verify date and time
|
|
||||||
ret = verify_open_hours(conf=config['HORAIRES'], log=logger)
|
|
||||||
# Verify caller phone number
|
|
||||||
ret, phone_number = verify_caller(buf=out, num=config['NUM_AUTORISE'], log=logger)
|
|
||||||
if not ret:
|
|
||||||
# Disconnect connexion
|
|
||||||
send_at_cmd(cmd="ATH", serObj=ser, log=logger)
|
|
||||||
logger.warning("Phone number not authorized : {}".format(phone_number))
|
|
||||||
else:
|
|
||||||
time.sleep(0.3)
|
|
||||||
# connect
|
|
||||||
ret = send_at_cmd(cmd='ATA', serObj=ser, log=logger)
|
|
||||||
if ret:
|
|
||||||
time.sleep(0.2)
|
|
||||||
# send DMTF tone
|
|
||||||
send_at_cmd(cmd='AT+VTS='+config['DTMF_CODE'], serObj=ser, log=logger)
|
|
||||||
time.sleep(0.5)
|
|
||||||
# Disconnect
|
|
||||||
ret = send_at_cmd(cmd='ATH', serObj=ser, log=logger)
|
|
||||||
if not ret:
|
|
||||||
logger.error('Cannot disconnect ...')
|
|
||||||
out = ''
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("error communicating: {}".format(e))
|
logger.error("Erreur de com série: {}".format(e))
|
||||||
else:
|
else:
|
||||||
logger.error("cannot open serial port")
|
logger.error("Impossible d'ouvrir le port série")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Verify if open or not
|
||||||
|
opened = verify_open_hours(conf=config['HORAIRES'], log=logger)
|
||||||
|
if opened:
|
||||||
|
# Si le module GSM doit être allumé et qu'il est éteint, on l'allume
|
||||||
|
if not GSM_MODULE_STATE:
|
||||||
|
logger.info("Allumage du module GSM HAT ...")
|
||||||
|
setup_module()
|
||||||
|
GSM_MODULE_STATE = True
|
||||||
|
# Attente de 5 secondes avant d'initier l'init GSM
|
||||||
|
time.sleep(5)
|
||||||
|
# Initialize GSM communication
|
||||||
|
ret = init_gsm_com(serObj=ser, config=config, logger=logger)
|
||||||
|
if not ret:
|
||||||
|
logger.error("Erreur d'initialisation de la com GSM avec le module")
|
||||||
|
ser.close()
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
# Si le module GSM doit être éteint et qu'il est allumé, on l'eteint
|
||||||
|
if GSM_MODULE_STATE:
|
||||||
|
logger.debug("Fermeture du module GSM HAT ...")
|
||||||
|
setup_module()
|
||||||
|
GSM_MODULE_STATE = False
|
||||||
|
|
||||||
|
# server_addr = "/tmp/uds_socket"
|
||||||
|
# # Make sure the socket does not already exist
|
||||||
|
# try:
|
||||||
|
# os.unlink(server_addr)
|
||||||
|
# except OSError:
|
||||||
|
# if os.path.exists(server_addr):
|
||||||
|
# raise
|
||||||
|
#
|
||||||
|
# # Create UDS socket
|
||||||
|
# sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
|
# # Bind the socket to the port
|
||||||
|
# sock.bind(server_addr)
|
||||||
|
# # Listen for incoming connections
|
||||||
|
# sock.listen(1)
|
||||||
|
# thread = Thread(target=listener, args=(sock, logger,))
|
||||||
|
# thread.start()
|
||||||
|
# time.sleep(1)
|
||||||
|
|
||||||
|
# Scheduler opened hours
|
||||||
|
sched = BackgroundScheduler(daemon=True)
|
||||||
|
sched.add_job(func=cron_verify_hours,
|
||||||
|
args=(config['HORAIRES'], logger),
|
||||||
|
trigger='cron',
|
||||||
|
minute='*',
|
||||||
|
id="task_verify_hours")
|
||||||
|
sched.start()
|
||||||
|
|
||||||
|
# if ser.isOpen():
|
||||||
|
# logger.info("Le port de communication avec le module GSM est ouvert")
|
||||||
|
# try:
|
||||||
|
# ser.flushInput() #flush input buffer, discarding all its contents
|
||||||
|
# ser.flushOutput() #flush output buffer, aborting current output
|
||||||
|
# if GSM_MODULE_STATE:
|
||||||
|
# # Initialize GSM communication
|
||||||
|
# ret = init_gsm_com(serObj=ser, config=config, logger=logger)
|
||||||
|
# if not ret:
|
||||||
|
# logger.error("Erreur d'initialisation de la communication avec le module GSM")
|
||||||
|
# return
|
||||||
|
# out = ''
|
||||||
|
# while True:
|
||||||
|
# # While the number of bytes in the input buffer > 0
|
||||||
|
# while ser.in_waiting > 0:
|
||||||
|
# # remove \r and \n chars from out string
|
||||||
|
# out += ser.read_until().decode('utf-8').replace('\r','').replace('\n','')
|
||||||
|
# if len(out) > 0 :
|
||||||
|
# logger.debug("out: {}".format(out))
|
||||||
|
# time.sleep(.1)
|
||||||
|
# if out.startswith('+CLIP: '):
|
||||||
|
# # Verify date and time
|
||||||
|
# ret = verify_open_hours(conf=config['HORAIRES'], log=logger)
|
||||||
|
# # Verify caller phone number
|
||||||
|
# ret, phone_number = verify_caller(buf=out, num=config['NUM_AUTORISE'], log=logger)
|
||||||
|
# if not ret:
|
||||||
|
# # Disconnect connexion
|
||||||
|
# send_at_cmd(cmd="ATH", serObj=ser, logger=logger)
|
||||||
|
# logger.warning("Phone number not authorized : {}".format(phone_number))
|
||||||
|
# else:
|
||||||
|
# logger.debug("Phone number authorized ...")
|
||||||
|
# time.sleep(0.3)
|
||||||
|
# # connect
|
||||||
|
# ret = send_at_cmd(cmd='ATA', serObj=ser, logger=logger)
|
||||||
|
# if ret:
|
||||||
|
# time.sleep(0.2)
|
||||||
|
# # send DMTF tone
|
||||||
|
# send_at_cmd(cmd='AT+VTS='+config['DTMF_CODE'], serObj=ser, logger=logger)
|
||||||
|
# time.sleep(0.5)
|
||||||
|
# # Disconnect
|
||||||
|
# ret = send_at_cmd(cmd='ATH', serObj=ser, logger=logger)
|
||||||
|
# if not ret:
|
||||||
|
# logger.error('Cannot disconnect ...')
|
||||||
|
# out = ''
|
||||||
|
# except Exception as e:
|
||||||
|
# logger.error("error communicating: {}".format(e))
|
||||||
|
# else:
|
||||||
|
# logger.error("cannot open serial port")
|
||||||
|
|
||||||
logger.info("fermeture du port de communication avec le GNSS_HAT")
|
logger.info("fermeture du port de communication avec le GNSS_HAT")
|
||||||
ser.close()
|
ser.close()
|
||||||
|
sched.shutdown(wait=False)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user