mirror of
https://github.com/Civlo85/gsmHat.git
synced 2026-05-06 21:08:10 +00:00
Call and GPS functionality added
This commit is contained in:
@@ -1,543 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
# Filename: gsmHat.py
|
||||
import logging
|
||||
import serial
|
||||
import threading
|
||||
import time
|
||||
import math
|
||||
import re
|
||||
from datetime import datetime
|
||||
import RPi.GPIO as GPIO
|
||||
|
||||
class SMS:
|
||||
def __init__(self):
|
||||
self.Message = ''
|
||||
self.Sender = ''
|
||||
self.Receiver = ''
|
||||
self.Date = ''
|
||||
|
||||
class GPS:
|
||||
EarthRadius = 6371e3 # meters
|
||||
|
||||
@staticmethod
|
||||
def CalculateDeltaP(Position1, Position2):
|
||||
phi1 = Position1.Latitude * math.pi / 180.0
|
||||
phi2 = Position2.Latitude * math.pi / 180.0
|
||||
deltaPhi = (Position2.Latitude - Position1.Latitude) * math.pi / 180.0
|
||||
deltaLambda = (Position2.Longitude - Position1.Longitude) * math.pi / 180.0
|
||||
|
||||
a = math.sin(deltaPhi / 2) * math.sin(deltaPhi / 2) + math.cos(phi1) * math.cos(phi2) * math.sin(deltaLambda / 2) * math.sin(deltaLambda / 2)
|
||||
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
|
||||
d = GPS.EarthRadius * c # in meters
|
||||
|
||||
return d
|
||||
|
||||
def __init__(self):
|
||||
self.GNSS_status = 0
|
||||
self.Fix_status = 0
|
||||
self.UTC = '' # yyyyMMddhhmmss.sss
|
||||
self.Latitude = 0.0 # ±dd.dddddd [-90.000000,90.000000]
|
||||
self.Longitude = 0.0 # ±ddd.dddddd [-180.000000,180.000000]
|
||||
self.Altitude = 0.0 # in meters
|
||||
self.Speed = 0.0 # km/h [0,999.99]
|
||||
self.Course = 0.0 # degrees [0,360.00]
|
||||
self.HDOP = 0.0 # [0,99.9]
|
||||
self.PDOP = 0.0 # [0,99.9]
|
||||
self.VDOP = 0.0 # [0,99.9]
|
||||
self.GPS_satellites = 0 # [0,99]
|
||||
self.GNSS_satellites = 0 # [0,99]
|
||||
self.Signal = 0.0 # % max = 55 dBHz
|
||||
|
||||
class GSMHat:
|
||||
"""GSM Hat Backend with SMS Functionality (for now)"""
|
||||
|
||||
regexGetSingleValue = r'([+][a-zA-Z\ ]+(:\ ))([\d]+)'
|
||||
regexGetAllValues = r'([+][a-zA-Z:\s]+)([\w\",\s+\/:.]+)'
|
||||
timeoutSerial = 5
|
||||
timeoutGPSActive = 1
|
||||
timeoutGPSInactive = 5
|
||||
|
||||
def __init__(self, SerialPort, Baudrate):
|
||||
self.__baudrate = Baudrate
|
||||
self.__port = SerialPort
|
||||
|
||||
self.__logger = logging.getLogger(__name__)
|
||||
self.__logger.setLevel(logging.INFO)
|
||||
self.__loggerFileHandle = logging.FileHandler('gsmHat.log')
|
||||
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||
self.__loggerFileHandle.setFormatter(formatter)
|
||||
self.__loggerFileHandle.setLevel(logging.INFO )
|
||||
self.__logger.addHandler(self.__loggerFileHandle)
|
||||
|
||||
self.__connect()
|
||||
self.__startWorking()
|
||||
|
||||
def __connect(self):
|
||||
self.__ser = serial.Serial(self.__port, self.__baudrate)
|
||||
self.__ser.flushInput()
|
||||
self.__serData = ''
|
||||
self.__writeLock = False
|
||||
self.__logger.info('Serial connection to '+self.__port+' established')
|
||||
|
||||
def __disconnect(self):
|
||||
self.__ser.close()
|
||||
|
||||
def __startWorking(self):
|
||||
self.__working = True
|
||||
self.__state = 1
|
||||
self.__smsToRead = 0
|
||||
self.__init = False
|
||||
self.__readRAW = False
|
||||
self.__smsToBuild = None
|
||||
self.__smsList = []
|
||||
self.__smsSendList = []
|
||||
self.__numberToCall = ''
|
||||
self.__sendHangUp = False
|
||||
self.__startGPS = False
|
||||
self.__GPSstarted = False
|
||||
self.__GPSstartSending = False
|
||||
self.__GPSstopSending = False
|
||||
self.__GPScollectData = False
|
||||
self.__GPSactualData = GPS()
|
||||
self.__GPStimeout = self.timeoutGPSInactive * 1000
|
||||
self.__GPSwaittime = 0
|
||||
self.__workerThread = threading.Thread(target=self.__workerThread, daemon=True)
|
||||
self.__workerThread.start()
|
||||
|
||||
def __stopWorking(self):
|
||||
self.__working = False
|
||||
self.__workerThread.join(10.0) # Timeout = 10.0 Seconds
|
||||
|
||||
def __sendToHat(self, string):
|
||||
if self.__writeLock == False:
|
||||
self.__lastCommand = string
|
||||
string = string + '\n'
|
||||
self.__ser.write(string.encode('iso-8859-1'))
|
||||
self.__writeLock = True
|
||||
self.__sentTimeout = int(round(time.time())) + self.timeoutSerial
|
||||
self.__logger.debug('Sent to hat: %s' % string)
|
||||
return True
|
||||
else:
|
||||
self.__logger.debug('Wait for Lock...')
|
||||
time.sleep(1)
|
||||
return False
|
||||
|
||||
def __pressPowerKey(self):
|
||||
GPIO.setmode(GPIO.BOARD)
|
||||
GPIO.setup(7, GPIO.OUT)
|
||||
while True:
|
||||
GPIO.output(7, GPIO.LOW)
|
||||
time.sleep(4)
|
||||
GPIO.output(7, GPIO.HIGH)
|
||||
break
|
||||
GPIO.cleanup()
|
||||
time.sleep(10)
|
||||
|
||||
def SMS_available(self):
|
||||
return len(self.__smsList)
|
||||
|
||||
def SMS_read(self):
|
||||
if self.SMS_available() > 0:
|
||||
retSMS = self.__smsList[0]
|
||||
del self.__smsList[0]
|
||||
return retSMS
|
||||
|
||||
return None
|
||||
|
||||
def SMS_write(self, NumberReceiver, Message):
|
||||
newSMS = SMS()
|
||||
newSMS.Receiver = NumberReceiver
|
||||
newSMS.Message = Message
|
||||
self.__smsSendList.append(newSMS)
|
||||
|
||||
def Call(self, Number, Timeout = 15):
|
||||
if self.__numberToCall == '':
|
||||
self.__numberToCall = str(Number)
|
||||
self.__callTimeout = Timeout
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def HangUp(self):
|
||||
self.__sendHangUp = True
|
||||
|
||||
def GetActualGPS(self):
|
||||
return self.__GPSactualData
|
||||
|
||||
def __startGPSUnit(self):
|
||||
self.__startGPS = True
|
||||
|
||||
def __startGPSsending(self):
|
||||
self.__GPSstartSending = True
|
||||
|
||||
def __stopGPSsending(self):
|
||||
self.__GPSstopSending = True
|
||||
|
||||
def __collectGPSData(self):
|
||||
self.__GPScollectData = True
|
||||
|
||||
def ColData(self):
|
||||
self.__collectGPSData()
|
||||
|
||||
def close(self):
|
||||
self.__disconnect()
|
||||
self.__logger.info('Serial connection to '+self.__port+' closed')
|
||||
self.__stopWorking()
|
||||
|
||||
def __processData(self):
|
||||
if self.__serData != '':
|
||||
if self.__readRAW:
|
||||
self.__logger.debug('Received Raw Data: %s' % self.__serData)
|
||||
if self.__serData == 'OK\r\n':
|
||||
self.__smsToBuild.Message = self.__smsToBuild.Message.rstrip('\r\n')
|
||||
self.__smsList.append(self.__smsToBuild)
|
||||
self.__readRAW = False
|
||||
self.__writeLock = False
|
||||
else:
|
||||
#self.__smsToBuild.Message = bytearray.fromhex(self.__serData).decode()
|
||||
self.__smsToBuild.Message = self.__smsToBuild.Message + self.__serData
|
||||
else:
|
||||
self.__logger.debug('Received Data: %s' % self.__serData)
|
||||
|
||||
if 'OK' in self.__serData:
|
||||
self.__writeLock = False
|
||||
self.__logger.debug('Lock Off')
|
||||
elif '+CME ERROR:' in self.__serData:
|
||||
self.__writeLock = False
|
||||
|
||||
match = re.findall(self.regexGetSingleValue, self.__serData)
|
||||
self.__cmeErr = int(match[0][1])
|
||||
|
||||
self.__logger.info('Got CME ERROR: %s' % match[0][1])
|
||||
elif '+CMS ERROR:' in self.__serData:
|
||||
self.__writeLock = False
|
||||
|
||||
match = re.findall(self.regexGetSingleValue, self.__serData)
|
||||
self.__cmsErr = int(match[0][1])
|
||||
|
||||
self.__logger.info('Got CMS ERROR: %s' % match[0][1])
|
||||
elif '+CPMS:' in self.__serData:
|
||||
match = re.findall(self.regexGetAllValues, self.__serData)
|
||||
rawData = match[0][1].split(',')
|
||||
self.__masSMSSpace = int(rawData[1])
|
||||
numSMS = int(rawData[0])
|
||||
if numSMS > 0:
|
||||
self.__smsToRead = 1
|
||||
|
||||
elif '+CMGR:' in self.__serData:
|
||||
# read SMS content
|
||||
match = re.findall(self.regexGetAllValues, self.__serData)
|
||||
rawData = match[0][1].split('","')
|
||||
self.__readRAW = True
|
||||
self.__smsToBuild = SMS()
|
||||
#self.__smsToBuild.Sender = bytearray.fromhex(rawData[1]).decode()
|
||||
self.__smsToBuild.Sender = rawData[1]
|
||||
self.__smsToBuild.Date = rawData[3].replace('"', '')
|
||||
self.__smsToBuild.Date = datetime.strptime(rawData[3].replace('"', '')[:-3], '%y/%m/%d,%H:%M:%S')
|
||||
self.__smsToBuild.Message = ''
|
||||
|
||||
# unannounced data reception below (e.g. new SMS oder phone call)
|
||||
elif '+CMTI:' in self.__serData:
|
||||
self.__logger.info('Received new SMS')
|
||||
match = re.findall(self.regexGetAllValues, self.__serData)
|
||||
rawData = match[0][1].split(',')
|
||||
storage = rawData[0]
|
||||
numSMS = int(rawData[1])
|
||||
self.__logger.debug('New SMS in memory ' + storage + ' at position ' + str(numSMS))
|
||||
self.__smsToRead = numSMS
|
||||
|
||||
# GPS Data coming here
|
||||
elif '+CGNSINF:' in self.__serData:
|
||||
self.__logger.debug('New GPS Data:')
|
||||
match = re.findall(self.regexGetAllValues, self.__serData)
|
||||
rawData = match[0][1].split(',')
|
||||
|
||||
newGPS = GPS()
|
||||
|
||||
try:
|
||||
newGPS.GNSS_status = int(rawData[0])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Fix_status = int(rawData[1])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.UTC = datetime.strptime(rawData[2][:-4], '%Y%m%d%H%M%S')
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Latitude = float(rawData[3])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Longitude = float(rawData[4])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Altitude = float(rawData[5])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Speed = float(rawData[6])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Course = float(rawData[7])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.HDOP = float(rawData[10])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.PDOP = float(rawData[11])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.VDOP = float(rawData[12])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.GPS_satellites = int(rawData[14])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.GNSS_satellites = int(rawData[15])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Signal = float(rawData[18])/55.0
|
||||
except:
|
||||
pass
|
||||
|
||||
self.__GPSactualData = newGPS
|
||||
|
||||
|
||||
self.__serData = ''
|
||||
|
||||
def __waitForUnlock(self):
|
||||
actTime = int(round(time.time()))
|
||||
if self.__sentTimeout > 0 and actTime > self.__sentTimeout:
|
||||
# Timeout
|
||||
self.__logger.error('Timeout during data reception')
|
||||
|
||||
if self.__state == 2:
|
||||
# It might be that the gsm module is not powered on
|
||||
# So let's try
|
||||
self.__logger.error('Try to restart gsm module')
|
||||
self.__pressPowerKey()
|
||||
self.__state = 1
|
||||
self.__writeLock = False
|
||||
self.__sentTimeout = 0
|
||||
return False
|
||||
else:
|
||||
raise 'Unhandled timeout during data reception'
|
||||
|
||||
if self.__writeLock:
|
||||
return False
|
||||
else:
|
||||
self.__sentTimeout = 0
|
||||
return True
|
||||
|
||||
def __workerThread(self):
|
||||
self.__logger.info('Worker started')
|
||||
self.__waitTime = 0
|
||||
|
||||
while self.__working:
|
||||
# Check for incoming chars
|
||||
while self.__ser.inWaiting() > 0:
|
||||
newChar = self.__ser.read().decode('iso-8859-1')
|
||||
|
||||
if newChar == '\n':
|
||||
if self.__readRAW == True:
|
||||
self.__serData += newChar
|
||||
self.__processData()
|
||||
else:
|
||||
if newChar == '\r':
|
||||
if self.__readRAW == True:
|
||||
self.__serData += newChar
|
||||
else:
|
||||
self.__serData += newChar
|
||||
|
||||
# Statemachine
|
||||
actTime = int(round(time.time() * 1000))
|
||||
if self.__state == 1:
|
||||
if self.__sendToHat('AT+CMGF=1'):
|
||||
self.__startGPSUnit()
|
||||
self.__stopGPSsending()
|
||||
self.__state = 2
|
||||
elif self.__state == 2:
|
||||
if self.__waitForUnlock():
|
||||
if self.__sendToHat('AT+CPMS="SM"'):
|
||||
self.__state = 3
|
||||
elif self.__state == 3:
|
||||
if self.__waitForUnlock():
|
||||
self.__state = 97
|
||||
self.__nextState = 2
|
||||
self.__waitTime = actTime + 5000
|
||||
elif self.__state == 20:
|
||||
# Read SMS
|
||||
if self.__sendToHat('AT+CMGR='+str(self.__smsToRead)):
|
||||
self.__state = 21
|
||||
elif self.__state == 21:
|
||||
if self.__waitForUnlock():
|
||||
if self.__smsToBuild == None:
|
||||
# An der Stelle self.__smsToRead gab es keine SMS zu lesen
|
||||
pass
|
||||
else:
|
||||
# Es gab eine neue SMS
|
||||
self.__smsToBuild = None
|
||||
|
||||
# Lösche die behandelte SMS an der Stelle
|
||||
if self.__sendToHat('AT+CMGD='+str(self.__smsToRead)):
|
||||
self.__state = 22
|
||||
|
||||
elif self.__state == 22:
|
||||
if self.__waitForUnlock():
|
||||
if(self.__smsToRead == 20):
|
||||
self.__smsToRead = 0
|
||||
else:
|
||||
self.__smsToRead = self.__smsToRead + 1
|
||||
|
||||
self.__state = 97
|
||||
self.__nextState = 2
|
||||
self.__waitTime = actTime + 5000
|
||||
|
||||
elif self.__state == 30:
|
||||
# SMS versenden
|
||||
retSMS = self.__smsSendList[0]
|
||||
messageString = 'AT+CMGS="' + retSMS.Receiver + '"\n' + retSMS.Message + '\x1A'
|
||||
self.timeoutSerial = 30
|
||||
if self.__sendToHat(messageString):
|
||||
self.__state = 31
|
||||
|
||||
elif self.__state == 31:
|
||||
if self.__waitForUnlock():
|
||||
retSMS = self.__smsSendList[0]
|
||||
self.__logger.info('Message to ' + retSMS.Receiver + ' successfully sent')
|
||||
del self.__smsSendList[0]
|
||||
self.timeoutSerial = 5
|
||||
|
||||
self.__state = 97
|
||||
self.__nextState = 2
|
||||
self.__waitTime = actTime + 5000
|
||||
|
||||
elif self.__state == 40:
|
||||
if self.__sendToHat('ATD' + self.__numberToCall + ';'):
|
||||
self.__state = 41
|
||||
|
||||
elif self.__state == 41:
|
||||
if self.__waitForUnlock():
|
||||
self.__waitTime = actTime + self.__callTimeout * 1000
|
||||
self.__state = 42
|
||||
|
||||
elif self.__state == 42:
|
||||
# Wait x Seconds
|
||||
if actTime > self.__waitTime or self.__sendHangUp == True:
|
||||
self.__numberToCall = ''
|
||||
self.__sendHangUp = True
|
||||
self.__state = 97
|
||||
self.__nextState = 2
|
||||
self.__waitTime = actTime + 5000
|
||||
|
||||
elif self.__state == 43:
|
||||
if self.__sendToHat('AT+CHUP'):
|
||||
self.__state = 44
|
||||
|
||||
elif self.__state == 44:
|
||||
if self.__waitForUnlock():
|
||||
self.__sendHangUp = False
|
||||
self.__state = 97
|
||||
self.__nextState = 2
|
||||
self.__waitTime = actTime + 5000
|
||||
|
||||
elif self.__state == 50:
|
||||
if self.__sendToHat('AT+CGNSPWR=1'):
|
||||
self.__state = 51
|
||||
|
||||
elif self.__state == 51:
|
||||
if self.__waitForUnlock():
|
||||
self.__logger.debug('GPS powered on')
|
||||
self.__startGPS = False
|
||||
self.__state = 97
|
||||
self.__nextState = 2
|
||||
self.__waitTime = actTime + 5000
|
||||
|
||||
elif self.__state == 52:
|
||||
if self.__sendToHat('AT+CGNSTST=1'):
|
||||
self.__state = 55
|
||||
self.__logger.debug('GPS start sending')
|
||||
self.__GPSstartSending = False
|
||||
|
||||
elif self.__state == 53:
|
||||
if self.__sendToHat('AT+CGNSTST=0'):
|
||||
self.__state = 55
|
||||
self.__GPSstopSending = False
|
||||
|
||||
elif self.__state == 54:
|
||||
if self.__sendToHat('AT+CGNSINF'):
|
||||
self.__state = 55
|
||||
self.__GPScollectData = False
|
||||
|
||||
elif self.__state == 55:
|
||||
if self.__waitForUnlock():
|
||||
self.__state = 97
|
||||
self.__nextState = 2
|
||||
self.__waitTime = actTime + 5000
|
||||
|
||||
elif self.__state == 97:
|
||||
# Check if new SMS to send is there
|
||||
if len(self.__smsSendList) > 0:
|
||||
self.__state = 30
|
||||
|
||||
# Check if we have to Call somebody
|
||||
elif self.__numberToCall != '':
|
||||
self.__state = 40
|
||||
|
||||
# Should I Hang Up ?
|
||||
elif self.__sendHangUp:
|
||||
self.__state = 43
|
||||
|
||||
# Check if new SMS is there
|
||||
elif self.__smsToRead > 0:
|
||||
self.__state = 20
|
||||
|
||||
# Check if GPS Unit should start
|
||||
elif self.__startGPS:
|
||||
self.__state = 50
|
||||
|
||||
# Check if GPS Unit should start send
|
||||
elif self.__GPSstartSending:
|
||||
self.__state = 52
|
||||
|
||||
# Check if GPS Unit should stop send
|
||||
elif self.__GPSstopSending:
|
||||
self.__state = 53
|
||||
|
||||
# Check if Single GPS Data should be collected
|
||||
elif self.__GPScollectData:
|
||||
self.__state = 54
|
||||
|
||||
elif actTime > self.__GPSwaittime:
|
||||
self.__GPScollectData = True
|
||||
self.__GPSwaittime = actTime + self.__GPStimeout
|
||||
|
||||
# Wait x Seconds
|
||||
elif actTime > self.__waitTime:
|
||||
self.__state = self.__nextState
|
||||
elif self.__state == 98:
|
||||
#Check if alive
|
||||
self.__logger.debug('Check if alive 98')
|
||||
if self.__sendToHat('AT'):
|
||||
self.__state = 99
|
||||
elif self.__state == 99:
|
||||
#Check if alive
|
||||
if self.__waitForUnlock():
|
||||
self.__state = 97
|
||||
self.__nextState = 98
|
||||
self.__waitTime = actTime + 5000
|
||||
|
||||
# Let other Threads also do their job
|
||||
time.sleep(0.1)
|
||||
self.__logger.info('Worker ended')
|
||||
+238
-3
@@ -4,6 +4,7 @@ import logging
|
||||
import serial
|
||||
import threading
|
||||
import time
|
||||
import math
|
||||
import re
|
||||
from datetime import datetime
|
||||
import RPi.GPIO as GPIO
|
||||
@@ -15,23 +16,57 @@ class SMS:
|
||||
self.Receiver = ''
|
||||
self.Date = ''
|
||||
|
||||
class GPS:
|
||||
EarthRadius = 6371e3 # meters
|
||||
|
||||
@staticmethod
|
||||
def CalculateDeltaP(Position1, Position2):
|
||||
phi1 = Position1.Latitude * math.pi / 180.0
|
||||
phi2 = Position2.Latitude * math.pi / 180.0
|
||||
deltaPhi = (Position2.Latitude - Position1.Latitude) * math.pi / 180.0
|
||||
deltaLambda = (Position2.Longitude - Position1.Longitude) * math.pi / 180.0
|
||||
|
||||
a = math.sin(deltaPhi / 2) * math.sin(deltaPhi / 2) + math.cos(phi1) * math.cos(phi2) * math.sin(deltaLambda / 2) * math.sin(deltaLambda / 2)
|
||||
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
|
||||
d = GPS.EarthRadius * c # in meters
|
||||
|
||||
return d
|
||||
|
||||
def __init__(self):
|
||||
self.GNSS_status = 0
|
||||
self.Fix_status = 0
|
||||
self.UTC = '' # yyyyMMddhhmmss.sss
|
||||
self.Latitude = 0.0 # ±dd.dddddd [-90.000000,90.000000]
|
||||
self.Longitude = 0.0 # ±ddd.dddddd [-180.000000,180.000000]
|
||||
self.Altitude = 0.0 # in meters
|
||||
self.Speed = 0.0 # km/h [0,999.99]
|
||||
self.Course = 0.0 # degrees [0,360.00]
|
||||
self.HDOP = 0.0 # [0,99.9]
|
||||
self.PDOP = 0.0 # [0,99.9]
|
||||
self.VDOP = 0.0 # [0,99.9]
|
||||
self.GPS_satellites = 0 # [0,99]
|
||||
self.GNSS_satellites = 0 # [0,99]
|
||||
self.Signal = 0.0 # % max = 55 dBHz
|
||||
|
||||
class GSMHat:
|
||||
"""GSM Hat Backend with SMS Functionality (for now)"""
|
||||
|
||||
regexGetSingleValue = r'([+][a-zA-Z\ ]+(:\ ))([\d]+)'
|
||||
regexGetAllValues = r'([+][a-zA-Z:\s]+)([\w\",\s+\/:]+)'
|
||||
regexGetAllValues = r'([+][a-zA-Z:\s]+)([\w\",\s+\/:.]+)'
|
||||
timeoutSerial = 5
|
||||
timeoutGPSActive = 1
|
||||
timeoutGPSInactive = 5
|
||||
|
||||
def __init__(self, SerialPort, Baudrate):
|
||||
self.__baudrate = Baudrate
|
||||
self.__port = SerialPort
|
||||
|
||||
self.__logger = logging.getLogger(__name__)
|
||||
self.__logger.setLevel(logging.DEBUG)
|
||||
self.__logger.setLevel(logging.INFO)
|
||||
self.__loggerFileHandle = logging.FileHandler('gsmHat.log')
|
||||
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||
self.__loggerFileHandle.setFormatter(formatter)
|
||||
self.__loggerFileHandle.setLevel(logging.DEBUG)
|
||||
self.__loggerFileHandle.setLevel(logging.INFO )
|
||||
self.__logger.addHandler(self.__loggerFileHandle)
|
||||
|
||||
self.__connect()
|
||||
@@ -56,6 +91,16 @@ class GSMHat:
|
||||
self.__smsToBuild = None
|
||||
self.__smsList = []
|
||||
self.__smsSendList = []
|
||||
self.__numberToCall = ''
|
||||
self.__sendHangUp = False
|
||||
self.__startGPS = False
|
||||
self.__GPSstarted = False
|
||||
self.__GPSstartSending = False
|
||||
self.__GPSstopSending = False
|
||||
self.__GPScollectData = False
|
||||
self.__GPSactualData = GPS()
|
||||
self.__GPStimeout = self.timeoutGPSInactive * 1000
|
||||
self.__GPSwaittime = 0
|
||||
self.__workerThread = threading.Thread(target=self.__workerThread, daemon=True)
|
||||
self.__workerThread.start()
|
||||
|
||||
@@ -105,6 +150,35 @@ class GSMHat:
|
||||
newSMS.Message = Message
|
||||
self.__smsSendList.append(newSMS)
|
||||
|
||||
def Call(self, Number, Timeout = 15):
|
||||
if self.__numberToCall == '':
|
||||
self.__numberToCall = str(Number)
|
||||
self.__callTimeout = Timeout
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def HangUp(self):
|
||||
self.__sendHangUp = True
|
||||
|
||||
def GetActualGPS(self):
|
||||
return self.__GPSactualData
|
||||
|
||||
def __startGPSUnit(self):
|
||||
self.__startGPS = True
|
||||
|
||||
def __startGPSsending(self):
|
||||
self.__GPSstartSending = True
|
||||
|
||||
def __stopGPSsending(self):
|
||||
self.__GPSstopSending = True
|
||||
|
||||
def __collectGPSData(self):
|
||||
self.__GPScollectData = True
|
||||
|
||||
def ColData(self):
|
||||
self.__collectGPSData()
|
||||
|
||||
def close(self):
|
||||
self.__disconnect()
|
||||
self.__logger.info('Serial connection to '+self.__port+' closed')
|
||||
@@ -171,6 +245,74 @@ class GSMHat:
|
||||
numSMS = int(rawData[1])
|
||||
self.__logger.debug('New SMS in memory ' + storage + ' at position ' + str(numSMS))
|
||||
self.__smsToRead = numSMS
|
||||
|
||||
# GPS Data coming here
|
||||
elif '+CGNSINF:' in self.__serData:
|
||||
self.__logger.debug('New GPS Data:')
|
||||
match = re.findall(self.regexGetAllValues, self.__serData)
|
||||
rawData = match[0][1].split(',')
|
||||
|
||||
newGPS = GPS()
|
||||
|
||||
try:
|
||||
newGPS.GNSS_status = int(rawData[0])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Fix_status = int(rawData[1])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.UTC = datetime.strptime(rawData[2][:-4], '%Y%m%d%H%M%S')
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Latitude = float(rawData[3])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Longitude = float(rawData[4])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Altitude = float(rawData[5])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Speed = float(rawData[6])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Course = float(rawData[7])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.HDOP = float(rawData[10])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.PDOP = float(rawData[11])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.VDOP = float(rawData[12])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.GPS_satellites = int(rawData[14])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.GNSS_satellites = int(rawData[15])
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
newGPS.Signal = float(rawData[18])/55.0
|
||||
except:
|
||||
pass
|
||||
|
||||
self.__GPSactualData = newGPS
|
||||
|
||||
|
||||
self.__serData = ''
|
||||
|
||||
@@ -222,6 +364,8 @@ class GSMHat:
|
||||
actTime = int(round(time.time() * 1000))
|
||||
if self.__state == 1:
|
||||
if self.__sendToHat('AT+CMGF=1'):
|
||||
self.__startGPSUnit()
|
||||
self.__stopGPSsending()
|
||||
self.__state = 2
|
||||
elif self.__state == 2:
|
||||
if self.__waitForUnlock():
|
||||
@@ -279,15 +423,106 @@ class GSMHat:
|
||||
self.__nextState = 2
|
||||
self.__waitTime = actTime + 5000
|
||||
|
||||
elif self.__state == 40:
|
||||
if self.__sendToHat('ATD' + self.__numberToCall + ';'):
|
||||
self.__state = 41
|
||||
|
||||
elif self.__state == 41:
|
||||
if self.__waitForUnlock():
|
||||
self.__waitTime = actTime + self.__callTimeout * 1000
|
||||
self.__state = 42
|
||||
|
||||
elif self.__state == 42:
|
||||
# Wait x Seconds
|
||||
if actTime > self.__waitTime or self.__sendHangUp == True:
|
||||
self.__numberToCall = ''
|
||||
self.__sendHangUp = True
|
||||
self.__state = 97
|
||||
self.__nextState = 2
|
||||
self.__waitTime = actTime + 5000
|
||||
|
||||
elif self.__state == 43:
|
||||
if self.__sendToHat('AT+CHUP'):
|
||||
self.__state = 44
|
||||
|
||||
elif self.__state == 44:
|
||||
if self.__waitForUnlock():
|
||||
self.__sendHangUp = False
|
||||
self.__state = 97
|
||||
self.__nextState = 2
|
||||
self.__waitTime = actTime + 5000
|
||||
|
||||
elif self.__state == 50:
|
||||
if self.__sendToHat('AT+CGNSPWR=1'):
|
||||
self.__state = 51
|
||||
|
||||
elif self.__state == 51:
|
||||
if self.__waitForUnlock():
|
||||
self.__logger.debug('GPS powered on')
|
||||
self.__startGPS = False
|
||||
self.__state = 97
|
||||
self.__nextState = 2
|
||||
self.__waitTime = actTime + 5000
|
||||
|
||||
elif self.__state == 52:
|
||||
if self.__sendToHat('AT+CGNSTST=1'):
|
||||
self.__state = 55
|
||||
self.__logger.debug('GPS start sending')
|
||||
self.__GPSstartSending = False
|
||||
|
||||
elif self.__state == 53:
|
||||
if self.__sendToHat('AT+CGNSTST=0'):
|
||||
self.__state = 55
|
||||
self.__GPSstopSending = False
|
||||
|
||||
elif self.__state == 54:
|
||||
if self.__sendToHat('AT+CGNSINF'):
|
||||
self.__state = 55
|
||||
self.__GPScollectData = False
|
||||
|
||||
elif self.__state == 55:
|
||||
if self.__waitForUnlock():
|
||||
self.__state = 97
|
||||
self.__nextState = 2
|
||||
self.__waitTime = actTime + 5000
|
||||
|
||||
elif self.__state == 97:
|
||||
# Check if new SMS to send is there
|
||||
if len(self.__smsSendList) > 0:
|
||||
self.__state = 30
|
||||
|
||||
# Check if we have to Call somebody
|
||||
elif self.__numberToCall != '':
|
||||
self.__state = 40
|
||||
|
||||
# Should I Hang Up ?
|
||||
elif self.__sendHangUp:
|
||||
self.__state = 43
|
||||
|
||||
# Check if new SMS is there
|
||||
elif self.__smsToRead > 0:
|
||||
self.__state = 20
|
||||
|
||||
# Check if GPS Unit should start
|
||||
elif self.__startGPS:
|
||||
self.__state = 50
|
||||
|
||||
# Check if GPS Unit should start send
|
||||
elif self.__GPSstartSending:
|
||||
self.__state = 52
|
||||
|
||||
# Check if GPS Unit should stop send
|
||||
elif self.__GPSstopSending:
|
||||
self.__state = 53
|
||||
|
||||
# Check if Single GPS Data should be collected
|
||||
elif self.__GPScollectData:
|
||||
self.__state = 54
|
||||
|
||||
elif actTime > self.__GPSwaittime:
|
||||
self.__GPScollectData = True
|
||||
self.__GPSwaittime = actTime + self.__GPStimeout
|
||||
|
||||
# Wait x Seconds
|
||||
elif actTime > self.__waitTime:
|
||||
self.__state = self.__nextState
|
||||
|
||||
Reference in New Issue
Block a user