# 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. # # Optionally give argument m=[ getLoc | getGSM ]. 'Presence' info includes signal strength, # battery level, phone profile and calendar availability (busy/free). # # getLoc (default action): # # 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 / 13.5.2008 from mod_python import apache 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 readGSM : def __init__(self) : self.readLocation() def readLocation(self) : self.count = 0 self.loopOut = 6 # 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 = readGSM() 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 createXMLReply(data): s = "\n" s = s + "\n" s = s + data s = s + "\n" return s def getLoc(): gps, gsm, presence = '', '', '' gps = fetchGPS() gsm = fetchGSM() presence = fetchPresence() s = gps + gsm + presence return s def getGSM(): gsm, presence = '', '' gsm = fetchGSM() presence = fetchPresence() s = gsm + presence return s def handler(req): req.content_type = 'text/xml' # # handler request can also have an arguments like m=getGSM # s = '' argument = req.args if argument != None: parts = argument.split('=') if parts[0] == 'm': if parts[1] == 'getGSM': s = getGSM() else: s = getLoc() else: s = getLoc() req.write( createXMLReply(s) ) return apache.OK