source: src/django_gheat/gheat/management/commands/import_droidstumbler.py@ 9317

Last change on this file since 9317 was 9183, checked in by rick, 14 years ago

Whoops forgot about 0 entries to import.

  • Property svn:executable set to *
File size: 5.8 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Script for importing DroidStumbler .csv files, which takes the best value of
5# each measurement point.
6#
7# Original by Dennis Wagenaar <d.wagenaar@gmail.com>
8#
9# Rick van der Zwet <info@rickvanderzwet.nl>
10#
11from django.core.management import setup_environ
12from django.core.management.base import BaseCommand, CommandError
13from django.db import connection, transaction
14from django.db.utils import IntegrityError
15from optparse import OptionParser, make_option
16from gheat.models import *
17import csv
18import datetime
19import gzip
20import logging
21import os
22import sys
23
24def user_feedback(output, count, dot_step, summary_report):
25 if (count % summary_report) == 0:
26 output.write(str(count))
27 elif (count % dot_step) == 0:
28 output.write(".")
29 output.flush()
30 return count + 1
31
32
33def import_droidstumbler(location, meetrondje, gebruiker, email, datum,show_progres=False,output=sys.stdout,bulk_import=True):
34 """ Import all points, return tuple with summary"""
35 g, created = Gebruiker.objects.get_or_create(naam=gebruiker , email=email)
36 a, created = Apparatuur.objects.get_or_create(antenne='buildin' , kaart='mobilePhone')
37 mr, created = MeetRondje.objects.get_or_create(datum=datum , naam=meetrondje , gebruiker=g , apparatuur=a)
38
39 meting_count = 0
40 new_ap_count = 0
41 ap_cache = {}
42 meting_pool = {}
43
44 if show_progres: output.write('#INFO: Pre-Processing file: ')
45 if location.endswith('.gz'):
46 fh = gzip.open(location,'rb')
47 else:
48 fh = open(location,'rb')
49 csvfile = csv.reader(fh, delimiter=',')
50 count = 0
51 for row in csvfile:
52 if show_progres: count = user_feedback(output, count, 100, 1000)
53 try:
54 epoch, msg_type, lat, lon, accuracy, ssid, bssid, level, frequency, capabilities = row
55 except ValueError:
56 logging.error("Unable to parse line:%i '%s'" % (csvfile.line_num, row))
57 continue
58 if msg_type == "data" and lat and lon:
59 if not ap_cache.has_key(bssid):
60 ap_cache[bssid], created = Accespoint.objects.get_or_create(mac=bssid, ssid=ssid, encryptie=capabilities)
61 if created: new_ap_count += 1
62
63 # We store the best value found
64 key = (ap_cache[bssid], lat, lon)
65 signaal=(100 + int(level))
66 if meting_pool.has_key(key):
67 meting_pool[key] = max(meting_pool[key], signaal)
68 else:
69 meting_pool[key] = signaal
70 if show_progres: output.write("%s\n" % count)
71
72
73 if show_progres: output.write('#INFO: Importing the data into the database: ')
74 meting_count = 0
75 cursor = connection.cursor()
76 sql_values = []
77 for (ap,lat,lon),signal in meting_pool.iteritems():
78 try:
79 if bulk_import:
80 value_str = str((int(mr.id),int(ap.id),float(lat),float(lon),int(signaal)))
81 sql_values.append(value_str)
82 else:
83 m = Meting.objects.create(meetrondje=mr, accespoint=ap, latitude=lat, longitude=lon, signaal=signaal)
84 except IntegrityError, e:
85 logging.error("Unable to import - %s" % e)
86 continue
87
88 # Give some feedback to the user
89 if show_progres: meting_count = user_feedback(output, meting_count, 100, 1000)
90
91 # Make sure to include closing newline
92 if show_progres: output.write("%s\n" % meting_count)
93
94 # Bulk Import data if possible
95 if bulk_import:
96 if len(sql_values) == 0:
97 logging.warn("No data to import")
98 else:
99 try:
100 sql = "INSERT INTO gheat_meting (`meetrondje_id`, `accespoint_id`, `lat`, `lng`, `signaal`) VALUES %s" % ','.join(sql_values)
101 cursor.execute(sql)
102 transaction.commit_unless_managed()
103 except IntegrityError, e:
104 logging.error("Unable to import - %s" % e)
105 pass
106
107 return (len(ap_cache), new_ap_count, meting_count, len(meting_pool) - meting_count)
108
109
110class Command(BaseCommand):
111 args = '<csvfile>[.gz] [csvfile2[.gz] [csvfile3[.gz] ...] '
112 option_list = BaseCommand.option_list + (
113 make_option('-m', '--meetrondje', dest='meetrondje', default=None),
114 make_option('-g', '--gebruiker', dest='gebruiker', default=os.environ['USER']),
115 make_option('-e', '--email', dest='email', default=os.environ['USER'] + '@example.org'),
116 make_option('-d', '--datum', dest='datum', default=None, help="Provide date \
117 in following format: %Y-%m-%d-%H%M%S, by default it will be generated from \
118 the filename"),)
119
120 def handle(self, *args, **options):
121 if len(args) == 0:
122 self.print_help(sys.argv[0],sys.argv[1])
123 raise CommandError("Not all arguments are provided")
124
125 for csv_file in args:
126 # Make sure to check files before we going to do importing at all
127 if not os.path.isfile(csv_file):
128 raise CommandError("csv file '%s' does not exists" % csv_file)
129 self.stdout.write("#INFO: Processing '%s'\n" % csv_file)
130
131 # Meetrondje from filename if needed
132 if options['meetrondje'] == None:
133 meetrondje = os.path.basename(csv_file).rstrip('.gz').rstrip('.csv')
134 else:
135 meetrondje = options['meetrondje']
136 # Date from filename if needed
137 if options['datum'] == None:
138 datum = os.path.basename(csv_file).lstrip('ScanResult-').rstrip('.csv.gz')
139 else:
140 datum = options['datum']
141 try:
142 datum = datetime.datetime.strptime(datum,'%Y-%m-%d-%H%M%S')
143 except ValueError:
144 raise CommandError("Invalid date '%s'\n" % options['datum'])
145
146 self.stdout.write('#INFO: Meetrondje: %s @ %s\n' % (meetrondje, datum))
147 self.stdout.write("#INFO: Going to import '%s' for gebruiker '%s <%s>'\n" % (os.path.basename(csv_file), options['gebruiker'], options['email']))
148 (ap_count, new_ap_count, meting_count, meting_error_count) = import_droidstumbler(csv_file,meetrondje,options['gebruiker'],options['email'], datum, True)
149 self.stdout.write("#INFO: Import summary accespoints: added:%s processed:%s\n" % (new_ap_count, ap_count))
150 self.stdout.write("#INFO: Import summary metingen: added:%s error:%s\n" % (meting_count, meting_error_count))
Note: See TracBrowser for help on using the repository browser.