# Copyright 2008 Nokia Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Read the GPS coordinates from bluetooth GPS device or internal GPS (if one of them
# exits) and GSM/WCDMA cell-id and presence' information and return them.
#
# Use either getLoc or getGSM. 'Presence' info includes signal strength, battery level, phone
# profile and calendar availability (busy/free).
#
# getLoc:
#
# Return mobile coordinates, speed, course, cell-id + presence information.
#
# In case of bluetooth Gps, the first time script is run, this will do bluetooth discovery to
# find a GPS device. If discovery is successfull then save the address of the found
# device to the file and use that one on the next time.
# If discovery fails, assume that the user does not have GPS device and write and empty entry to
# the file. Next time skip the GPS part and return only cell-id.
# The user can delete the address file from the mobile phone and therefore force script to make
# bluetooth discovery again
#
# getGSM:
#
# Return the cell-id + presence information.
#
#
# Created: Timo Alakoski / 20.1.2008
import e32
import location
import socket
import time
import string
import re
import sysinfo
import os
import calendar
try:
import positioning
except ImportError:
PositioningModule = False
else:
PositioningModule = True
#
# Connect to the GPS device.
#
# If bluetooth GPS device found, save it to the disk and use it next time.
#
class BluetoothGPS:
def __init__(self):
self.success = ''
self.addressDir= u'c:\\Data'
self.addressFile= self.addressDir + '\\gpsaddress.txt'
self.sock = ''
self.tryConnect()
def tryConnect(self):
address = self.readLastAddress()
if (address == 'nofile'): # no bt address found, try discovery
self.success = self.connect('')
elif (address == ''): # file exists but it's empty, skip gps
return
else: # address found, try to connect
self.success = self.connect(address)
def connect(self, address):
try:
self.sock = socket.socket(socket.AF_BT,socket.SOCK_STREAM)
if (address != ''):
target = (address, 1)
else:
btaddress, services = socket.bt_discover()
print "Discovered: %s, %s"%(btaddress, services)
target = (btaddress, services.values()[0])
print "Connecting to " + str(target)
self.sock.connect(target)
except socket.error: # sock.connect and socket.bt_discover come here
self.sock.close()
print "Can not connect to (" + address +")"
if (address == ''): # bt discovery failed, write empty file and never do discovery again
self.writeLastAddress('')
return ''
if (address == ''): # bt discovery succeeded, write address and use it allways
self.writeLastAddress(target[0])
return 'ok'
def close(self):
if (self.sock):
self.sock.close()
def getPacket(self):
if (self.success) :
return GPSPacket(self.sock)
else:
return 0
def readLastAddress(self):
try:
file = open(self.addressFile,'r')
addr = file.readline()
file.close()
except IOError:
print "Can't read the file: " + self.addressFile
return 'nofile'
return string.strip(addr)
def writeLastAddress(self, addr):
try:
if (not os.path.exists(self.addressDir)) :
os.mkdir(self.addressDir)
file = open(self.addressFile,'w')
a = addr + '\n' # add newline
file.write(a)
file.close()
except IOError:
print "Can't write the file: " + self.addressFile
return ''
print "Bt address " + addr + "written to " + self.addressFile
#
# Read the input from the bluetooth GPS device.
#
# Loops the input (max 10 times) until $GPRMC record is found.
#
class GPSPacket:
def __init__(self, sock):
self.lat = "";
self.lon = "";
self.sock = sock
ch = self.sock.recv(1)
packetReceived = 0
self.loopOut = 100
# Loop until packet received
while(packetReceived < self.loopOut):
buffer = ""
try:
ch = self.sock.recv(1)
while(ch !='\n'):
buffer+=ch
ch = self.sock.recv(1)
except socker.error:
print "Connection broken while reading data"
break
# print "(%d) %s" % (packetReceived, buffer)
packetReceived += 1
# print buffer
if (buffer[0:6]=="$GPRMC"):
gsmData = buffer.split(",")
# Parse the GPS packet
self.GPRMC = gsmData[0]
self.utc = gsmData[1]
self.status = gsmData[2]
self.lat = gsmData[3]
self.latns = gsmData[4]
self.lon = gsmData[5]
self.lonew = gsmData[6]
self.knots = gsmData[7]
self.course = gsmData[8]
self.date = gsmData[9]
self.xx1 = gsmData[10]
self.xx2 = gsmData[11]
# Break the loop execution
if (self.lat != '' and self.lon !=''):
break
def fetchLatLonSign(self, nswe):
if (nswe == 'S' or nswe == 's' or nswe == 'W' or nswe == 'w'):
return "-"
else:
return ""
def convertDecimalDegrees(self, gpsString):
r = re.search('(^.+)(..\..+)', gpsString) # 02457.6712
degrees = float(r.group(1)) # 024
decimals = float(r.group(2))/60 # 57.6712
v = degrees + decimals + 0.0000000001 # 24 + 0.961186666666666666 + 0.0000001
v = str(v).replace(',','.') # sometimes 24,96 -> 24.96
r = re.search('^.+\..{6}', v) # regex dies if less than 6 decimals
return r.group() # 24.961186
def getLat(self):
if (self.status == 'A'):
return self.fetchLatLonSign(self.latns) + self.convertDecimalDegrees(self.lat)
else:
return ''
def getLon(self):
if (self.status == 'A'):
return self.fetchLatLonSign(self.lonew) + self.convertDecimalDegrees(self.lon)
else:
return ''
def getSpeed(self):
if (self.status == 'A'):
speed = 1.852 * float(self.knots) # convert knots to km/h
return str(speed)
else:
return ''
def getCourse(self):
if (self.status == 'A'):
return self.course
else:
return ''
#
# Gets the coordinated from the phones which have Location API (i.e. N95)
#
class InternalGPS :
def __init__(self) :
#positioning.select_module(positioning.default_module())
positioning.set_requestors([{"type":"service","format":"application","data":"raccoonloc.py"}])
self.data = ''
self.count = 0
self.loopOut = 10
# Loop max loopOut times to get coordinates
while(self.count < self.loopOut):
pos = positioning.position(course=1,satellites=1,partial=1)
if (pos['position']['latitude'] != 0): # i.e. latitude != NaN
self.data = pos
break
time.sleep(1)
self.count += 1
def getLat(self) :
return str( self.data['position']['latitude'] )
def getLon(self) :
return str( self.data['position']['longitude'] )
def getAccuracy(self) :
return str( self.data['position']['horizontal_accuracy'] )
def getSpeed(self) :
self.v = self.data['course']['speed']
if (self.v != 0):
return str( self.v )
else:
return ''
def getCourse(self) :
self.v = self.data['course']['heading']
if (self.v != 0):
return str( self.v )
else:
return ''
def getDebugCount(self):
return str( self.count )
def close(self):
positioning.stop_position()
#
# Reads the GSM location, i.e. cell-id info
#
# If no GSM coverage, then location.gsm_location returns 0,0,0,0
#
class GSM :
def __init__(self) :
self.readLocation()
def readLocation(self) :
self.count = 0
self.loopOut = 10
# Loop max loopOut times to get cell id. Trying to solve the problem with the 3rd Ed. phones
while(self.count < self.loopOut):
loc = location.gsm_location()
if (loc is not None):
(self.mcc, self.mnc, self.lac, self.cellid) = loc
break
else:
# 3rd Ed. S60 phones return None without certificate
# 3rd Ed. S60 phones seems to return None sometimes also with cerficate
(self.mcc, self.mnc, self.lac, self.cellid) = (0, 0, 0, 0)
time.sleep(1)
self.count += 1
def getMcc(self) :
return str(self.mcc)
def getMnc(self):
return str(self.mnc)
def getLac(self):
return str(self.lac)
def getCellid(self):
return str(self.cellid)
def getDebugCount(self):
return str(self.count)
def close(self) :
pass
#
# Read the presence information of the phone
#
class PRESENCE:
def __init__(self) :
return
def getScriptId(self) :
id = "raccoonloc_s60v" + str(e32.s60_version_info[0]) + "." + str(e32.s60_version_info[1])
return id
def getBatteryLevel(self) :
return str(sysinfo.battery())
def getSignalStrength(self) :
return str(sysinfo.signal())
def getActiveProfile(self) :
if (e32.pys60_version_info[:3] >= (1, 3, 15)):
return sysinfo.active_profile()
else:
return ''
def getCalendarStatus(self) :
db=calendar.open()
now = time.time()
appointments = db.daily_instances(now, appointments=1)
for instance in appointments:
entry=db[instance['id']]
if (entry.start_time < now and entry.end_time > now):
return 'busy'
return 'free'
def fetchBluetoothGPS() :
lat, lon, speed, course = '', '', '', ''
gps = BluetoothGPS()
if (gps.success):
packet = gps.getPacket()
lat = packet.getLat()
lon = packet.getLon()
speed = packet.getSpeed()
course = packet.getCourse()
gps.close()
s = " " + lat + "\n"
s = s + " " + lon + "\n"
s = s + " " + speed + "\n"
s = s + " " + course + "\n"
return s
def fetchInternalGPS() :
lat, lon, accuracy, speed, course = '', '', '', '', ''
debugCount = ''
gps = InternalGPS()
if (gps.data):
lat = gps.getLat()
lon = gps.getLon()
accuracy = gps.getAccuracy()
speed = gps.getSpeed()
course = gps.getCourse()
debugCount = gps.getDebugCount()
gps.close()
s = " " + lat + "\n"
s = s + " " + lon + "\n"
s = s + " " + lon + "\n"
s = s + " " + speed + "\n"
s = s + " " + course + "\n"
s = s + " " + debugCount + "\n";
return s
def fetchGPS():
if (PositioningModule):
return fetchInternalGPS()
else:
return fetchBluetoothGPS()
def fetchGSM() :
mcc, mnc, lac, sellid = '', '', '', ''
debugCellCount = ''
gsm = GSM()
mcc = gsm.getMcc()
mnc = gsm.getMnc()
lac = gsm.getLac()
cellid = gsm.getCellid()
debugCount = gsm.getDebugCount()
gsm.close()
s = " " + mcc + "\n"
s = s + " " + mnc + "\n"
s = s + " " + lac + "\n"
s = s + " " + cellid + "\n"
s = s + " " + debugCount + "\n";
return s
def fetchPresence() :
presence = PRESENCE()
id = presence.getScriptId()
battery = presence.getBatteryLevel()
signal = presence.getSignalStrength()
profile = presence.getActiveProfile()
calendarStatus = presence.getCalendarStatus()
s = " " + id + "\n"
s = s + " " + battery + "\n"
s = s + " " + signal + "\n"
s = s + " " + profile + "\n"
s = s + " " + calendarStatus + "\n"
return s
def getLoc(req):
req.content_type = 'text/xml'
gps, gsm, presence = '', '', ''
gps = fetchGPS()
gsm = fetchGSM()
presence = fetchPresence()
s = gps + gsm + presence
return createXMLReply(s)
def getGSM(req):
req.content_type = 'text/xml'
gsm, presence = '', ''
gsm = fetchGSM()
presence = fetchPresence()
s = gsm + presence
return createXMLReply(s)
def createXMLReply(data):
s = "\n"
s = s + "\n"
s = s + data
s = s + "\n"
return s