copie d'une base de données vierge et conforme si elle n'existe pas
This commit is contained in:
+102
-71
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
# @author: benoit.vince84@free.fr
|
# @author: benoit.vince84@free.fr
|
||||||
# @date: Septembre 2022
|
# @date: Septembre 2022
|
||||||
# @brief: Programme Intercom à partir du module GSM du GNSS_HAT
|
# @brief: Programme Intercom à partir du module GSM
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
# Importation de modules externes #
|
# Importation de modules externes #
|
||||||
@@ -16,8 +16,9 @@ import RPi.GPIO as GPIO
|
|||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
import calendar
|
import calendar
|
||||||
import json
|
import json
|
||||||
from jsonschema import validate
|
import jsonschema
|
||||||
import socket
|
import socket
|
||||||
|
import shutil
|
||||||
from signal import signal, SIGINT
|
from signal import signal, SIGINT
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from apscheduler.schedulers.background import BackgroundScheduler
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
@@ -26,54 +27,65 @@ from apscheduler.schedulers.background import BackgroundScheduler
|
|||||||
# Class et Methods #
|
# Class et Methods #
|
||||||
|
|
||||||
def validate_json(json_data={}, logger=None):
|
def validate_json(json_data={}, logger=None):
|
||||||
''' Validate json by schema
|
''' Validate json database by schema
|
||||||
|
|
||||||
:param json_data:
|
:param json_data:
|
||||||
json data loaded
|
json data loaded
|
||||||
|
|
||||||
:param logger:
|
:param logger:
|
||||||
werkzeug context
|
logger object
|
||||||
|
|
||||||
:return int:
|
:return bool:
|
||||||
0 => If validates with 2.0
|
True if OK, otherwise False
|
||||||
1 => otherwise
|
|
||||||
'''
|
'''
|
||||||
|
if not isinstance(logger, log.Logger):
|
||||||
|
return False
|
||||||
if not isinstance(json_data, dict):
|
if not isinstance(json_data, dict):
|
||||||
logger.error("error parameter, expecting dict, get {}".format(type(json_data)))
|
logger.error("error parameter, expecting dict, get {}".format(type(json_data)))
|
||||||
return False
|
return False
|
||||||
if not isinstance(logger, log.Logger):
|
|
||||||
logger.error("error parameter, expecting logging.Logger, get {}".format(type(logger)))
|
|
||||||
return False
|
|
||||||
|
|
||||||
ret = True
|
ret = True
|
||||||
try:
|
try:
|
||||||
with open(os.path.join('/home/pi', 'db.json.schema'), 'r') as f:
|
with open(os.path.join('/home/pi', 'db.json.schema'), 'r') as f:
|
||||||
schema=json.load(f)
|
schema=json.load(f)
|
||||||
try:
|
|
||||||
validate(instance=json_data, schema=schema)
|
|
||||||
except jsonschema.exceptions.ValidationError as e:
|
|
||||||
logger.error("Validator error")
|
|
||||||
ret = False
|
|
||||||
except jsonschema.exceptions.SchemaError as e:
|
|
||||||
logger.error("Schema error")
|
|
||||||
ret = False
|
|
||||||
except FileNotFoundError as e:
|
except FileNotFoundError as e:
|
||||||
logger.error("Impossible d'ouvrir le fichier de validation ({})".format(e))
|
logger.error("Impossible d'ouvrir le fichier de validation ({})".format(e))
|
||||||
ret = False
|
ret = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
jsonschema.validate(instance=json_data, schema=schema)
|
||||||
|
except jsonschema.exceptions.ValidationError as e:
|
||||||
|
logger.error("Erreur de validation de la base de données : {}".format(e))
|
||||||
|
ret = False
|
||||||
|
except jsonschema.exceptions.SchemaError as e:
|
||||||
|
logger.error("Erreur de schéma : {}".format(e))
|
||||||
|
ret = False
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def get_conf(logger=None):
|
def get_conf(logger=None):
|
||||||
''' Get configuration
|
''' Get configuration
|
||||||
|
|
||||||
|
:param logger:
|
||||||
|
logger object
|
||||||
|
|
||||||
:return dict:
|
:return dict:
|
||||||
Configuration dictionnary
|
Configuration dictionnary
|
||||||
'''
|
'''
|
||||||
if not isinstance(logger, log.Logger):
|
if not isinstance(logger, log.Logger):
|
||||||
logger.error("error parameter, expecting logging.Logger, get {}".format(type(logger)))
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
config = None
|
config = None
|
||||||
|
|
||||||
|
# copy database if not exists
|
||||||
|
if not os.path.exists(os.path.join("/etc/kineintercom", "db.json")):
|
||||||
|
logger.warning("Le fichier de la base de données n'existe pas ...")
|
||||||
|
try:
|
||||||
|
shutil.copyfile(os.path.join("/usr/share/kineintercom", "database_origin.json"),
|
||||||
|
os.path.join("/etc/kineintercom", "db.json"))
|
||||||
|
except PermissionError as e:
|
||||||
|
logger.error("Erreur de permission: {}".format(e))
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
with open(os.path.join("/etc/kineintercom", "db.json"), 'r') as f:
|
with open(os.path.join("/etc/kineintercom", "db.json"), 'r') as f:
|
||||||
try:
|
try:
|
||||||
@@ -100,7 +112,7 @@ def send_at_cmd(cmd='', timeout=0.0, serObj=None, logger=None):
|
|||||||
:param serObj:
|
:param serObj:
|
||||||
serial object
|
serial object
|
||||||
|
|
||||||
:param log:
|
:param logger:
|
||||||
logger object
|
logger object
|
||||||
|
|
||||||
:return int:
|
:return int:
|
||||||
@@ -121,7 +133,7 @@ def send_at_cmd(cmd='', timeout=0.0, serObj=None, logger=None):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if timeout > 0.0:
|
if timeout > 0.0:
|
||||||
serObj.timeout = timeout
|
serObj.timeout = timeout + 0.1
|
||||||
else:
|
else:
|
||||||
serObj.timeout = None
|
serObj.timeout = None
|
||||||
serObj.write(bytes(cmd+'\r', 'utf-8'))
|
serObj.write(bytes(cmd+'\r', 'utf-8'))
|
||||||
@@ -129,19 +141,12 @@ def send_at_cmd(cmd='', timeout=0.0, serObj=None, logger=None):
|
|||||||
out = ''
|
out = ''
|
||||||
outlst = []
|
outlst = []
|
||||||
while serObj.in_waiting > 0:
|
while serObj.in_waiting > 0:
|
||||||
#c = serObj.read(1).decode('utf-8', 'replace')
|
|
||||||
#if c == '\r' or c == '\n':
|
|
||||||
# if out != '':
|
|
||||||
# outlst.append(out)
|
|
||||||
# out = ''
|
|
||||||
#else:
|
|
||||||
# out += c
|
|
||||||
|
|
||||||
# remove \r and \n chars from out string
|
# remove \r and \n chars from out string
|
||||||
out += serObj.read_until().decode('utf-8', 'replace').replace('\r','').replace('\n','')
|
out += serObj.read_until().decode('utf-8', 'replace').replace('\r','').replace('\n','')
|
||||||
if out != '':
|
if out != '':
|
||||||
outlst.append(out)
|
outlst.append(out)
|
||||||
out = ''
|
out = ''
|
||||||
|
time.sleep(timeout)
|
||||||
logger.debug("Reponse: {}".format(outlst))
|
logger.debug("Reponse: {}".format(outlst))
|
||||||
if 'OK' in outlst:
|
if 'OK' in outlst:
|
||||||
return 0, outlst
|
return 0, outlst
|
||||||
@@ -162,16 +167,23 @@ def send_at_cmd(cmd='', timeout=0.0, serObj=None, logger=None):
|
|||||||
|
|
||||||
def set_sim_pin(serObj=None, pin_actif=False, code_pin="", logger=None):
|
def set_sim_pin(serObj=None, pin_actif=False, code_pin="", logger=None):
|
||||||
''' Set SIM PIN if necessary
|
''' Set SIM PIN if necessary
|
||||||
|
|
||||||
|
AT+CPIN=<CODE PIN> : Enter PIN (response READY: MT is not pending for any password)
|
||||||
|
|
||||||
:param serObj:
|
:param serObj:
|
||||||
serial object
|
serial object
|
||||||
|
|
||||||
:param config:
|
:param pin_actif:
|
||||||
dictionary config object from JSON database
|
attribute from dictionary config object
|
||||||
|
|
||||||
|
:param code_pin:
|
||||||
|
attribute from dictionary config object
|
||||||
|
|
||||||
:param log:
|
:param log:
|
||||||
logger object
|
logger object
|
||||||
|
|
||||||
:return bool:
|
:return bool:
|
||||||
|
True if OK, otherwise False
|
||||||
'''
|
'''
|
||||||
if not isinstance(logger, log.Logger):
|
if not isinstance(logger, log.Logger):
|
||||||
return False
|
return False
|
||||||
@@ -196,28 +208,30 @@ def set_sim_pin(serObj=None, pin_actif=False, code_pin="", logger=None):
|
|||||||
elif ret == 1:
|
elif ret == 1:
|
||||||
logger.warning("Timeout avec la commande AT: {}".format('AT+CPIN?'))
|
logger.warning("Timeout avec la commande AT: {}".format('AT+CPIN?'))
|
||||||
else:
|
else:
|
||||||
if rsp[1].split('+CPIN: ')[1] == 'SIM PIN':
|
for item in rsp:
|
||||||
logger.info('SIM verrouillée ...')
|
if item.startswith('+CPIN:'):
|
||||||
# Must enter SIM PIN
|
if item.split('+CPIN: ')[1] == 'SIM PIN':
|
||||||
if not pin_actif:
|
logger.info('SIM verrouillée ...')
|
||||||
logger.error("Configuration en conflit avec la réponse du module GSM")
|
# Must enter SIM PIN
|
||||||
return False
|
if not pin_actif:
|
||||||
else:
|
logger.error("Configuration en conflit avec la réponse du module GSM")
|
||||||
# Enter the SIM PIN configured in database
|
return False
|
||||||
ret, rsp = send_at_cmd(cmd='AT+CPIN='+code_pin,
|
else:
|
||||||
timeout=0.0,
|
# Enter the SIM PIN configured in database
|
||||||
serObj=serObj,
|
ret, _ = send_at_cmd(cmd='AT+CPIN='+code_pin,
|
||||||
logger=logger)
|
timeout=2.0,
|
||||||
if ret == 2:
|
serObj=serObj,
|
||||||
logger.error("Erreur avec la commande AT: {}".format('AT+CPIN=<CODE_PIN>'))
|
logger=logger)
|
||||||
return False
|
if ret == 2:
|
||||||
elif ret == 1:
|
logger.error("Erreur avec la commande AT: {}".format('AT+CPIN=<CODE_PIN>'))
|
||||||
logger.warning("Timeout avec la commande AT: {}".format('AT+CPIN=<CODE_PIN>'))
|
return False
|
||||||
else:
|
elif ret == 1:
|
||||||
logger.info("code PIN saisi ...")
|
logger.warning("Timeout avec la commande AT: {}".format('AT+CPIN=<CODE_PIN>'))
|
||||||
elif rsp[1].split('+CPIN: ')[1] == 'READY':
|
else:
|
||||||
# SIM PIN already notified
|
logger.info("code PIN validé ...")
|
||||||
logger.info('SIM déverrouillée ...')
|
elif item.split('+CPIN: ')[1] == 'READY':
|
||||||
|
# SIM PIN already notified
|
||||||
|
logger.info('SIM déverrouillée ...')
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -227,15 +241,11 @@ def init_gsm_com(serObj=None, config={}, logger=None):
|
|||||||
AT : test command
|
AT : test command
|
||||||
ATE1 :
|
ATE1 :
|
||||||
AT+CMEE=2 :
|
AT+CMEE=2 :
|
||||||
AT+CPIN? : Enter PIN (response READY: MT is not pending for any password
|
|
||||||
AT+CREG? : Network registration - return the status of result code
|
|
||||||
AT+CSQ :
|
|
||||||
AT+CLTS=1 :
|
AT+CLTS=1 :
|
||||||
AT+CMGF=1 : Set the format of messages to Text mode
|
AT+CMGF=1 : Set the format of messages to Text mode
|
||||||
AT+CLIP=1 : The calling line identifty (CLI) of calling party when
|
AT+CLIP=1 : The calling line identifty (CLI) of calling party when
|
||||||
receiving a mobile terminated call
|
receiving a mobile terminated call
|
||||||
AT+VTD=1 : Tone Duration (in 1/10 seconds)
|
AT+VTD=1 : Tone Duration (in 1/10 seconds)
|
||||||
ATS0=2 : Set Number of Ring before Automatically Answering the call
|
|
||||||
|
|
||||||
:param serObj:
|
:param serObj:
|
||||||
serial object
|
serial object
|
||||||
@@ -247,6 +257,7 @@ def init_gsm_com(serObj=None, config={}, logger=None):
|
|||||||
logger object
|
logger object
|
||||||
|
|
||||||
:return bool:
|
:return bool:
|
||||||
|
True if OK, otherwise False
|
||||||
'''
|
'''
|
||||||
if not isinstance(logger, log.Logger):
|
if not isinstance(logger, log.Logger):
|
||||||
return False
|
return False
|
||||||
@@ -288,11 +299,11 @@ def update_gsm_com(serObj=None, config={}, logger=None):
|
|||||||
:param config:
|
:param config:
|
||||||
dictionary config object from JSON database
|
dictionary config object from JSON database
|
||||||
|
|
||||||
:param log:
|
:param logger:
|
||||||
logger object
|
logger object
|
||||||
|
|
||||||
:return bool:
|
:return bool:
|
||||||
True if ok, otherwise False
|
True if OK, otherwise False
|
||||||
'''
|
'''
|
||||||
if not isinstance(logger, log.Logger):
|
if not isinstance(logger, log.Logger):
|
||||||
return False
|
return False
|
||||||
@@ -322,7 +333,7 @@ def info_gsm_com(serObj=None, config={}, logger=None):
|
|||||||
:param config:
|
:param config:
|
||||||
dictionary config object from JSON database
|
dictionary config object from JSON database
|
||||||
|
|
||||||
:param log:
|
:param logger:
|
||||||
logger object
|
logger object
|
||||||
|
|
||||||
:return bool:
|
:return bool:
|
||||||
@@ -442,22 +453,21 @@ def verify_caller(buf="", num="", logger=None):
|
|||||||
:param num:
|
:param num:
|
||||||
Caller phone number
|
Caller phone number
|
||||||
|
|
||||||
:param log:
|
:param logger:
|
||||||
logger object
|
logger object
|
||||||
|
|
||||||
:return bool:
|
:return bool:
|
||||||
True if authorized, False otherwise
|
True if authorized, False otherwise
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
if not isinstance(logger, log.Logger):
|
||||||
|
return False, ""
|
||||||
if not isinstance(buf, str):
|
if not isinstance(buf, str):
|
||||||
logger.error("error parameter, expecting str, get {}".format(type(buf)))
|
logger.error("error parameter, expecting str, get {}".format(type(buf)))
|
||||||
return False, ""
|
return False, ""
|
||||||
if not isinstance(num, str):
|
if not isinstance(num, str):
|
||||||
logger.error("error parameter, expecting str, get {}".format(type(num)))
|
logger.error("error parameter, expecting str, get {}".format(type(num)))
|
||||||
return False, ""
|
return False, ""
|
||||||
if not isinstance(logger, log.Logger):
|
|
||||||
logger.error("error parameter, expecting logging.Logger, get {}".format(type(logger)))
|
|
||||||
return False, ""
|
|
||||||
|
|
||||||
outlst = buf[7:].split(',')
|
outlst = buf[7:].split(',')
|
||||||
logger.debug("=> {}".format(outlst))
|
logger.debug("=> {}".format(outlst))
|
||||||
@@ -469,6 +479,12 @@ def verify_caller(buf="", num="", logger=None):
|
|||||||
|
|
||||||
def listener(sock, logger):
|
def listener(sock, logger):
|
||||||
''' Thread socket listener
|
''' Thread socket listener
|
||||||
|
|
||||||
|
:param sock:
|
||||||
|
socket object
|
||||||
|
|
||||||
|
:param logger:
|
||||||
|
logger object
|
||||||
'''
|
'''
|
||||||
|
|
||||||
global FLAG_CONF_UPDATE
|
global FLAG_CONF_UPDATE
|
||||||
@@ -509,13 +525,13 @@ def listener(sock, logger):
|
|||||||
logger.debug("Fin du serveur de communication")
|
logger.debug("Fin du serveur de communication")
|
||||||
return
|
return
|
||||||
|
|
||||||
def verify_open_hours(conf=None, logger=None):
|
def verify_open_hours(conf={}, logger=None):
|
||||||
''' Verify if GSM HAT must be opened with conf hours
|
''' Verify if GSM HAT must be opened with conf hours
|
||||||
|
|
||||||
:param conf:
|
:param conf:
|
||||||
configuration object
|
configuration object
|
||||||
|
|
||||||
:param log:
|
:param logger:
|
||||||
logger object
|
logger object
|
||||||
|
|
||||||
:return bool:
|
:return bool:
|
||||||
@@ -523,6 +539,9 @@ def verify_open_hours(conf=None, logger=None):
|
|||||||
'''
|
'''
|
||||||
if not isinstance(logger, log.Logger):
|
if not isinstance(logger, log.Logger):
|
||||||
return False
|
return False
|
||||||
|
if not isinstance(conf, dict):
|
||||||
|
logger.error("error parameter, expecting dict, get {}".format(type(conf)))
|
||||||
|
return False
|
||||||
|
|
||||||
flag = False
|
flag = False
|
||||||
my_date = date.today()
|
my_date = date.today()
|
||||||
@@ -542,6 +561,9 @@ def verify_open_hours(conf=None, logger=None):
|
|||||||
|
|
||||||
def init_module():
|
def init_module():
|
||||||
''' initialisation of GNSS/GPS/GSM HAT Module
|
''' initialisation of GNSS/GPS/GSM HAT Module
|
||||||
|
|
||||||
|
:return bool:
|
||||||
|
True if OK, otherwise False
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
GPIO.setmode(GPIO.BOARD)
|
GPIO.setmode(GPIO.BOARD)
|
||||||
@@ -553,6 +575,9 @@ def init_module():
|
|||||||
|
|
||||||
def setup_module():
|
def setup_module():
|
||||||
''' Setup module (Set/Reset)
|
''' Setup module (Set/Reset)
|
||||||
|
|
||||||
|
:return bool:
|
||||||
|
True if OK, otherwise False
|
||||||
'''
|
'''
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
@@ -565,9 +590,18 @@ def setup_module():
|
|||||||
#GPIO.cleanup()
|
#GPIO.cleanup()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def cron_verify_hours(op=None, config=None, logger=None):
|
def cron_verify_hours(op='', config=None, logger=None):
|
||||||
''' cron job to check opened or closed hours
|
''' cron job to check opened or closed hours
|
||||||
'''
|
'''
|
||||||
|
if not isinstance(logger, log.Logger):
|
||||||
|
return
|
||||||
|
if not isinstance(config, dict):
|
||||||
|
logger.error("error parameter, expecting dict, get {}".format(type(config)))
|
||||||
|
return
|
||||||
|
if not isinstance(op, str):
|
||||||
|
logger.error("error parameter, expecting str, get {}".format(type(op)))
|
||||||
|
return
|
||||||
|
|
||||||
global GSM_MODULE_STATE
|
global GSM_MODULE_STATE
|
||||||
global GSM_MODULE_INIT_STATE
|
global GSM_MODULE_INIT_STATE
|
||||||
if op == 'Horaires':
|
if op == 'Horaires':
|
||||||
@@ -678,7 +712,7 @@ def main():
|
|||||||
hl = log.FileHandler(os.path.join('/var/log/KineIntercom','Intercom.log'))
|
hl = log.FileHandler(os.path.join('/var/log/KineIntercom','Intercom.log'))
|
||||||
fl.setLevel(log.DEBUG)
|
fl.setLevel(log.DEBUG)
|
||||||
hl.setLevel(log.INFO)
|
hl.setLevel(log.INFO)
|
||||||
formatter = log.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
formatter = log.Formatter('%(asctime)s - %(funcName)s - %(levelname)s - %(message)s')
|
||||||
fl.setFormatter(formatter)
|
fl.setFormatter(formatter)
|
||||||
hl.setFormatter(formatter)
|
hl.setFormatter(formatter)
|
||||||
logger.addHandler(fl)
|
logger.addHandler(fl)
|
||||||
@@ -773,9 +807,6 @@ def main():
|
|||||||
else:
|
else:
|
||||||
GSM_MODULE_INIT_STATE = True
|
GSM_MODULE_INIT_STATE = True
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
# Retreive GSM infos
|
# Retreive GSM infos
|
||||||
logger.info('Récupération des infos du module ...')
|
logger.info('Récupération des infos du module ...')
|
||||||
ret = info_gsm_com(serObj=ser, config=config, logger=logger)
|
ret = info_gsm_com(serObj=ser, config=config, logger=logger)
|
||||||
|
|||||||
Reference in New Issue
Block a user