Exemplo n.º 1
0
 def init_launcher(self):
     self.rm = RocketManager()
     self.rm.acquire_devices()
Exemplo n.º 2
0
 def init_launcher(self):
     self.rm=RocketManager()
     self.rm.acquire_devices()
Exemplo n.º 3
0
class Scanner():
    def __init__(self, wireless, x=0, y=0):
        self.w = Wireless(wireless)
        self.rm = None
        self.x = x
        self.y = y
        self.aps = {}

    def init_launcher(self):
        self.rm = RocketManager()
        self.rm.acquire_devices()

    def step(self, dir, steps=1, sane=False):
        if not self.rm: self.init_launcher()
        c = 0
        while c < steps:
            if dir == RIGHT:
                if sane or self.x > 0: self.x -= 1
                else: break
            elif dir == LEFT:
                if sane or self.x < HMAX: self.x += 1
                else: break
            elif dir == UP:
                if sane or self.y < VMAX: self.y += 1
                else: break
            elif dir == DOWN:
                if sane or self.y > 0: self.y -= 1
                else: break
            self.rm.launchers[0].start_movement(dir)
            self.rm.launchers[0].stop_movement()
            c += 1
        if c == steps:
            return True

    def home(self):
        if not self.rm: self.init_launcher()
        print "press c-c when in home position"
        while True:
            print s.x
            try:
                s.step(RIGHT, steps=200, sane=True)
            except KeyboardInterrupt:
                self.rm.launchers[0].stop_movement()
                sys.exit(0)

    def scan(self, c=1, cb=None):
        res = []
        for _ in xrange(c):
            tmp = []
            for h in self.w.scan():
                try:
                    name = h.essid.decode('utf8')
                except:
                    name = h.bssid
                # TODO add
                # "Quality: Quality ", self.quality.quality
                # "Signal ", self.quality.getSignallevel()
                # "Noise ", self.quality.getNoiselevel()
                # "Encryption:", map(lambda x: hex(ord(x)), self.encode)
                # "Frequency:", self.frequency.getFrequency(), "(Channel", self.frequency.getChannel(self.range), ")"
                record = (self.x, self.y, datetime.now().isoformat(), h.bssid,
                          h.quality.getSignallevel(), name.strip())
                tmp.append(record)
            if cb: tmp = cb(tmp)
            res.extend(tmp)

        # handle callback
        for ap in res:
            # print all scan records
            print u' '.join([unicode(f) for f in ap])
            # remember all entries for later
            self.store(*ap)

        return res

    def store(self, x, y, date, bssid, rssi, name):
        try:
            self.aps[bssid]['rssi'].append((date, int(rssi), int(x), int(y)))
        except:
            self.aps[bssid] = {
                'name': name.strip(),
                'rssi': [(date, int(rssi), int(x), int(y))]
            }

    def fasth(self, c=1, steps=10, cb=None, sweeps=1):
        res = []
        dirs = [LEFT, RIGHT]
        for i in xrange(sweeps):
            while True:
                aps = self.scan(c)
                if cb: aps = cb(aps)
                res.extend(aps)
                if not self.step(dirs[i % 2], steps):
                    break
            if self.y == 0:
                self.movetoy(VMAX)
            else:
                self.movetoy(0)
        return res

    def apRSSI(self, target, batch):
        # x, y, date, bssid, rssi, name
        data = [
            item[4] for item in batch
            if item[3] == target and int(item[4]) > -100
        ]
        if data:
            rssi = sum(data) / float(len(data))
            print >> sys.stderr, "%4s %4s %3.2f |%s" % (self.x, self.y, rssi,
                                                        '▬' * int(rssi + 100))
        else:
            print >> sys.stderr, "%4s %4s        |" % (self.x, self.y)
        return batch

    def apCount(self, batch):
        # x, y, date, bssid, rssi, name
        count = len(set([item[3] for item in batch]))
        print >> sys.stderr, "%4s %4s %s %s" % (self.x, self.y, count,
                                                '▬' * count)
        return batch

    def stats(self):
        # do some stats on the seen APs
        stats = sorted(
            [(sum([int(rssi)
                   for _, rssi, _, _ in v['rssi'] if rssi != '-256']) /
              len(v['rssi']),
              max([int(rssi)
                   for _, rssi, _, _ in v['rssi'] if rssi != '-256']),
              min([int(rssi)
                   for _, rssi, _, _ in v['rssi'] if rssi != '-256']),
              max([int(rssi)
                   for _, rssi, _, _ in v['rssi'] if rssi != '-256']) -
              min([int(rssi)
                   for _, rssi, _, _ in v['rssi'] if rssi != '-256']), key,
              v['name']) for key, v in self.aps.items()],
            reverse=True)
        print >> sys.stderr, "avg mx mn sprd key name"
        for avg, mx, mn, sprd, key, name in stats:
            print >> sys.stderr, key, avg, mx, mn, sprd, self.aps[key]['name']

        for ap in s.ordered(by='dir'):
            print "|%s| %4s %3s %s %s %s %s" % (self.apspark(
                s.aps[ap[0]]), ap[4], ap[5], ap[2][:19], ap[0], ap[3], ap[1])

    def apspark(self, ap):
        radar = [[0, 0] for _ in xrange(20)]
        for item in sorted(ap['rssi'], key=itemgetter(2)):
            radar[int(item[2] / ((HMAX + 1.0) / 20))][0] += item[1]
            radar[int(item[2] / ((HMAX + 1.0) / 20))][1] += 1
        tmp = [x[0] / x[1] if x[1] else None for x in radar]
        if not [x for x in tmp if x]:
            return "%s" % ' ' * 20
        tmp = [
            y or min([x for x in tmp if x]) -
            ((max([x for x in tmp if x]) - min([x for x in tmp if x])) / 8) - 1
            for y in tmp
        ]
        return "%s" % s.spark(tmp).encode('utf8')

    def load(self, file):
        for line in file.readlines():
            try:
                self.store(*line.split(' ', 5))
            except TypeError:
                pass

    def ordered(self, by='dir'):
        if by == 'rssi': sortby = 3
        else: sortby = 4
        return sorted(
            [(ap, data['name']) + max(data['rssi'], key=itemgetter(1))
             for ap, data in self.aps.items()],
            key=itemgetter(sortby))

    def spark(self, data):
        lo = float(min(data))
        hi = float(max(data))
        incr = (hi - lo) / (len(blocks) - 1) or 1
        return ''.join([(blocks[int((float(n) - lo) / incr)] if n else ' ')
                        for n in data])

    def movetox(self, x):
        dir = LEFT if self.x <= x else RIGHT
        dist = self.x - x if x <= self.x else x - self.x
        self.step(dir, dist)

    def movetoy(self, y):
        dir = UP if self.y <= y else DOWN
        dist = self.y - y if y <= self.y else y - self.y
        self.step(dir, dist)

    def randomdir(self, plane, dir):
        oplane = plane
        odir = dir
        # choose another direction
        while dir == odir and plane == oplane:
            plane = random.randint(0, 2) % 2
            dir = random.randint(0, 1)
        return (plane, dir)

    def lock(self, target):
        # use with - where the param to tail controls how many past scans to consider:
        # cat $(ls -rt logs/*.log | tail -5) | ./wscan.py lock <bssid> >logs/$(date '+%s').log
        top = sorted(self.aps[target]['rssi'], key=itemgetter(1), reverse=True)
        sample_size = 30 if len(top) > 30 else len(top)
        posx = sum([x[2] for x in top][:sample_size]) / sample_size
        posy = sum([x[3] for x in top][:sample_size]) / sample_size
        rssi = sum([x[1] for x in top][:sample_size]) / sample_size
        # go to last known best position
        print >> sys.stderr, "|%s| %4s %4s %4s" % (self.apspark(
            self.aps[target]), posx, posy, rssi)
        self.movetox(posx)
        self.movetoy(posy)

        prev = None
        dirs = [[LEFT, RIGHT], [UP, DOWN]]
        plane, dir = self.randomdir(None, None)
        steps = 97
        lost = 0
        best = None

        try:
            while True:
                # scan a bit
                pop = 15

                #samples=[x[4] for x in self.scan(c=pop, cb=partial(self.apRSSI,target)) if x[3]==target]
                samples = self.scan(c=pop)
                self.apRSSI(target, samples)
                # only our own samples
                samples = [x[4] for x in samples if x[3] == target]

                # avg rssi in this direction
                # avg is fixed with missing readings, using -100db
                rssi = (sum(samples) + (-100 *
                                        (pop - len(samples)))) / float(pop)

                if not rssi:
                    if lost > 5: break
                    lost += 1
                    if lost == 3 and best:
                        # retry from last best position
                        self.movetox(best[1])
                        self.movetoy(best[2])
                        plane, dir = self.randomdir(plane, dir)
                else:
                    lost = 0
                # FIXME: more efficient search algo than below

                if best and (int(best[0]) - 3) > int(rssi):
                    # signal degraded, backtrack
                    # retry from last best position
                    self.movetox(best[1])
                    self.movetoy(best[2])
                    plane, dir = self.randomdir(plane, dir)
                    continue

                if not best or best[0] < rssi:
                    best = (rssi, self.x, self.y)

                if (prev and int(prev) - 2 > int(rssi)):
                    # signal degraded
                    self.step(dirs[plane][(dir + 1) % 2],
                              steps / ((plane * 4) + 1))
                    plane, dir = self.randomdir(plane, dir)
                    continue
                prev = rssi

                # wander mindlessly
                if not self.step(dirs[plane][dir], steps / ((plane * 4) + 1)):
                    # we hit some boundary, let's rebound
                    plane, dir = self.randomdir(plane, dir)

        except KeyboardInterrupt:
            pass
        # go home
        self.movetoy(0)
        self.movetox(0)
Exemplo n.º 4
0
class Scanner():
    def __init__(self, wireless, x=0, y=0):
        self.w=Wireless(wireless)
        self.rm=None
        self.x=x
        self.y=y
        self.aps={}

    def init_launcher(self):
        self.rm=RocketManager()
        self.rm.acquire_devices()

    def step(self,dir,steps=1, sane=False):
        if not self.rm: self.init_launcher()
        c=0
        while c<steps:
            if dir==RIGHT:
                if sane or self.x>0: self.x-=1
                else: break
            elif dir==LEFT:
                if sane or self.x<HMAX: self.x+=1
                else: break
            elif dir==UP:
                if sane or self.y<VMAX: self.y+=1
                else: break
            elif dir==DOWN:
                if sane or self.y>0: self.y-=1
                else: break
            self.rm.launchers[0].start_movement(dir)
            self.rm.launchers[0].stop_movement()
            c+=1
        if c==steps:
            return True

    def home(self):
        if not self.rm: self.init_launcher()
        print "press c-c when in home position"
        while True:
            print s.x
            try:
                s.step(RIGHT,steps=200, sane=True)
            except KeyboardInterrupt:
                self.rm.launchers[0].stop_movement()
                sys.exit(0)

    def scan(self,c=1, cb=None):
        res=[]
        for _ in xrange(c):
            tmp=[]
            for h in self.w.scan():
                try:
                    name=h.essid.decode('utf8')
                except:
                    name=h.bssid
                # TODO add
                # "Quality: Quality ", self.quality.quality
                # "Signal ", self.quality.getSignallevel()
                # "Noise ", self.quality.getNoiselevel()
                # "Encryption:", map(lambda x: hex(ord(x)), self.encode)
                # "Frequency:", self.frequency.getFrequency(), "(Channel", self.frequency.getChannel(self.range), ")"
                record=(self.x,
                        self.y,
                        datetime.now().isoformat(),
                        h.bssid,
                        h.quality.getSignallevel(),
                        name.strip())
                tmp.append(record)
            if cb: tmp=cb(tmp)
            res.extend(tmp)

        # handle callback
        for ap in res:
            # print all scan records
            print u' '.join([unicode(f) for f in ap])
            # remember all entries for later
            self.store(*ap)

        return res

    def store(self, x, y, date, bssid, rssi, name):
        try:
            self.aps[bssid]['rssi'].append((date, int(rssi), int(x), int(y)))
        except:
            self.aps[bssid]={'name': name.strip(),
                             'rssi': [(date, int(rssi), int(x), int(y))]}

    def fasth(self, c=1, steps=10, cb=None, sweeps=1):
        res=[]
        dirs=[LEFT, RIGHT]
        for i in xrange(sweeps):
            while True:
                aps=self.scan(c)
                if cb: aps=cb(aps)
                res.extend(aps)
                if not self.step(dirs[i%2],steps):
                    break
            if self.y==0:
                self.movetoy(VMAX)
            else:
                self.movetoy(0)
        return res

    def apRSSI(self, target, batch):
        # x, y, date, bssid, rssi, name
        data=[item[4] for item in batch if item[3]==target and int(item[4])>-100]
        if data:
            rssi=sum(data)/float(len(data))
            print >>sys.stderr, "%4s %4s %3.2f |%s" % (self.x, self.y, rssi, '▬'*int(rssi+100))
        else:
            print >>sys.stderr, "%4s %4s        |" % (self.x, self.y)
        return batch

    def apCount(self, batch):
        # x, y, date, bssid, rssi, name
        count=len(set([item[3] for item in batch]))
        print >>sys.stderr, "%4s %4s %s %s" % (self.x, self.y, count, '▬'*count)
        return batch

    def stats(self):
        # do some stats on the seen APs
        stats=sorted([(sum([int(rssi) for _, rssi, _, _ in v['rssi'] if rssi!='-256'])/len(v['rssi']),
                       max([int(rssi) for _, rssi, _, _ in v['rssi'] if rssi!='-256']),
                       min([int(rssi) for _, rssi, _, _ in v['rssi'] if rssi!='-256']),
                       max([int(rssi) for _, rssi, _, _ in v['rssi'] if rssi!='-256'])-min([int(rssi) for _, rssi, _, _ in v['rssi'] if rssi!='-256']),
                       key,
                       v['name'])
                      for key, v in self.aps.items()],
                     reverse=True)
        print >>sys.stderr, "avg mx mn sprd key name"
        for avg, mx, mn, sprd, key, name in stats:
            print >>sys.stderr, key, avg, mx, mn, sprd, self.aps[key]['name']

        for ap in s.ordered(by='dir'):
            print "|%s| %4s %3s %s %s %s %s" % (self.apspark(s.aps[ap[0]]), ap[4], ap[5], ap[2][:19], ap[0], ap[3], ap[1])

    def apspark(self, ap):
        radar=[[0,0] for _ in xrange(20)]
        for item in sorted(ap['rssi'],key=itemgetter(2)):
            radar[int(item[2]/((HMAX+1.0)/20))][0]+=item[1]
            radar[int(item[2]/((HMAX+1.0)/20))][1]+=1
        tmp=[x[0]/x[1] if x[1] else None for x in radar]
        if not [x for x in tmp if x]:
            return "%s" % ' '*20
        tmp=[y or min([x for x in tmp if x])-((max([x for x in tmp if x])-min([x for x in tmp if x]))/8)-1 for y in tmp]
        return "%s" % s.spark(tmp).encode('utf8')

    def load(self,file):
        for line in file.readlines():
            try:
                self.store(*line.split(' ',5))
            except TypeError:
                pass

    def ordered(self, by='dir'):
        if by=='rssi': sortby=3
        else: sortby=4
        return sorted([(ap, data['name'])+max(data['rssi'], key=itemgetter(1))
                       for ap, data in self.aps.items()],
                      key=itemgetter(sortby))

    def spark(self, data):
        lo = float(min(data))
        hi = float(max(data))
        incr = (hi - lo)/(len(blocks)-1) or 1
        return ''.join([(blocks[int((float(n) - lo)/incr)]
                        if n else
                        ' ')
                       for n in data])

    def movetox(self,x):
        dir=LEFT if self.x <= x else RIGHT
        dist=self.x - x if x <= self.x else x - self.x
        self.step(dir,dist)

    def movetoy(self,y):
        dir=UP if self.y <= y else DOWN
        dist=self.y - y if y <= self.y else y - self.y
        self.step(dir,dist)

    def randomdir(self, plane, dir):
        oplane=plane
        odir=dir
        # choose another direction
        while dir==odir and plane==oplane:
            plane=random.randint(0,2)%2
            dir=random.randint(0,1)
        return (plane, dir)

    def lock(self, target):
        # use with - where the param to tail controls how many past scans to consider:
        # cat $(ls -rt logs/*.log | tail -5) | ./wscan.py lock <bssid> >logs/$(date '+%s').log
        top=sorted(self.aps[target]['rssi'], key=itemgetter(1), reverse=True)
        sample_size=30 if len(top)>30 else len(top)
        posx=sum([x[2] for x in top][:sample_size])/sample_size
        posy=sum([x[3] for x in top][:sample_size])/sample_size
        rssi=sum([x[1] for x in top][:sample_size])/sample_size
        # go to last known best position
        print >>sys.stderr, "|%s| %4s %4s %4s" % (self.apspark(self.aps[target]), posx, posy, rssi)
        self.movetox(posx)
        self.movetoy(posy)

        prev=None
        dirs=[[LEFT,RIGHT],[UP,DOWN]]
        plane, dir=self.randomdir(None,None)
        steps=97
        lost=0
        best=None

        try:
            while True:
                # scan a bit
                pop=15

                #samples=[x[4] for x in self.scan(c=pop, cb=partial(self.apRSSI,target)) if x[3]==target]
                samples=self.scan(c=pop)
                self.apRSSI(target, samples)
                # only our own samples
                samples=[x[4] for x in samples if x[3]==target]

                # avg rssi in this direction
                # avg is fixed with missing readings, using -100db
                rssi=(sum(samples)+(-100*(pop-len(samples))))/float(pop)

                if not rssi:
                    if lost>5: break
                    lost+=1
                    if lost==3 and best:
                        # retry from last best position
                        self.movetox(best[1])
                        self.movetoy(best[2])
                        plane,dir=self.randomdir(plane,dir)
                else:
                    lost=0
                # FIXME: more efficient search algo than below

                if best and (int(best[0])-3)>int(rssi):
                    # signal degraded, backtrack
                    # retry from last best position
                    self.movetox(best[1])
                    self.movetoy(best[2])
                    plane,dir=self.randomdir(plane,dir)
                    continue

                if not best or best[0]<rssi:
                    best=(rssi, self.x, self.y)

                if (prev and int(prev)-2>int(rssi)):
                    # signal degraded
                    self.step(dirs[plane][(dir+1)%2], steps/((plane*4)+1))
                    plane,dir=self.randomdir(plane,dir)
                    continue
                prev=rssi

                # wander mindlessly
                if not self.step(dirs[plane][dir], steps/((plane*4)+1)):
                    # we hit some boundary, let's rebound
                    plane,dir=self.randomdir(plane,dir)

        except KeyboardInterrupt:
            pass
        # go home
        self.movetoy(0)
        self.movetox(0)