-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
484 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#!/usr/bin/python3 | ||
import json | ||
import requests | ||
import datetime | ||
from uuid import getnode as get_mac | ||
|
||
class HTTPPostHelper: | ||
def __init__(self, Id, Name,PostAddress): | ||
self.Id = Id | ||
self.Name = Name | ||
# getting mac address on fly so there would be less configurations | ||
self.mac = "".join(c + ":" if i % 2 else c for i, c in enumerate(hex(get_mac())[2:].zfill(12)))[:-1] | ||
self.PostAddress = PostAddress | ||
self.sended = False | ||
self.beaconData_ = [] | ||
|
||
def postData(self): | ||
#generating needed json structure | ||
|
||
|
||
data = { | ||
'id': self.Id, | ||
'name': self.Name, | ||
'mac' : self.mac, | ||
'ts' : str(datetime.datetime.utcnow()), | ||
'data' : self.beaconData_ | ||
} | ||
#print(json.dumps(data)) | ||
response = requests.post(self.PostAddress, json=json.dumps(data)) | ||
if response.status_code == 200 : | ||
self.sended = True | ||
else: | ||
self.sended = False | ||
|
||
|
||
def startPosting(self,BeaconData): | ||
# check if the data is posted before flushing it | ||
# if data is not postet it will append new data to the list | ||
if self.sended: | ||
# print('Posted') | ||
self.beaconData_.clear() | ||
self.beaconData_.extend(BeaconData) | ||
else: | ||
self.beaconData_.extend(BeaconData) | ||
|
||
self.postData() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
 | ||
|
||
# SBCGateway | ||
This is a gateway for ubeac project. | ||
It will Scan for **[ble advertisements](https://en.wikipedia.org/wiki/Bluetooth_advertising)** and send them to **[ubeac](http://ui.ubeac.io)** servers. | ||
|
||
## Getting started | ||
For running this project you will need a fresh installation of [raspbian lite](https://www.raspberrypi.org/downloads/raspbian/) on Bluetooth enable [RaspberryPi](https://www.raspberrypi.org/products/). | ||
You need to have [python 3](https://www.python.org/), [pybluez](https://github.com/pybluez/pybluez) and [requests](http://docs.python-requests.org/en/master/). | ||
|
||
You can get the project from our [Git Repository](https://github.com/ubeac/SBCGateway) | ||
|
||
### Config.ini | ||
postAddress is the link to the listener provided from [ubeac](http://ui.ubeac.io) or for debug you can use [HookServer](http://hook.ubeac.io). | ||
|
||
Set the id and name as you want. | ||
|
||
postInterval is the time laps between posts to the ubeac server.It's in seconds and you can set it to less than a second by providing a decimal. | ||
|
||
scanBuffer is the amount of scans beacon scanner do before sending data to post thread minimum number is 1 and you can set it to 100 if you are posting data to server slowly. | ||
|
||
If the scanBuffer is to much higher than postIntervals you will end up with some empty posts. | ||
|
||
### Running The project | ||
|
||
After configuring your device and editing config.ini you can run it by running abcScanner.py as **root** | ||
``` | ||
$ sudo python3 sbcScanner.py | ||
``` | ||
For Detailed instructions on how to config your raspberry pi and run this project read [readmeDetail.md](https://github.com/ubeac/SBCGateway/blob/master/readmeDetail.md) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
#!/usr/bin/python3 | ||
# performs a simple device inquiry, followed by a remote name request of each | ||
# discovered device | ||
|
||
import os | ||
import sys | ||
import struct | ||
import bluetooth._bluetooth as bluez | ||
import bluetooth | ||
import datetime | ||
|
||
class InqueryHelper: | ||
def __init__(self,dev_id=0): | ||
self.dev_id = dev_id | ||
self.sock = '' | ||
try: | ||
self.sock = bluez.hci_open_dev(self.dev_id) | ||
except: | ||
print("error accessing bluetooth device...") | ||
sys.exit(1) | ||
|
||
try: | ||
mode = self.read_inquiry_mode(self.sock) | ||
except Exception as e: | ||
print("error reading inquiry mode. ") | ||
print("Are you sure this a bluetooth 1.2 device?") | ||
print(e) | ||
sys.exit(1) | ||
print("current inquiry mode is %d" % mode) | ||
|
||
if mode != 1: | ||
print("writing inquiry mode...") | ||
try: | ||
result = self.write_inquiry_mode(self.sock, 1) | ||
except Exception as e: | ||
print("error writing inquiry mode. Are you sure you're root?") | ||
print(e) | ||
sys.exit(1) | ||
if result != 0: | ||
print("error while setting inquiry mode") | ||
print("result: %d" % result) | ||
|
||
|
||
def printpacket(self,pkt): | ||
for c in pkt: | ||
sys.stdout.write("%02x " % struct.unpack("B",c)[0]) | ||
print() | ||
|
||
|
||
def read_inquiry_mode(self,sock): | ||
"""returns the current mode, or -1 on failure""" | ||
# save current filter | ||
old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) | ||
|
||
# Setup socket filter to receive only events related to the | ||
# read_inquiry_mode command | ||
flt = bluez.hci_filter_new() | ||
opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, | ||
bluez.OCF_READ_INQUIRY_MODE) | ||
bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) | ||
bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); | ||
bluez.hci_filter_set_opcode(flt, opcode) | ||
sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) | ||
|
||
# first read the current inquiry mode. | ||
bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, | ||
bluez.OCF_READ_INQUIRY_MODE ) | ||
|
||
pkt = sock.recv(255) | ||
|
||
status,mode = struct.unpack("xxxxxxBB", pkt) | ||
if status != 0: mode = -1 | ||
|
||
# restore old filter | ||
sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) | ||
return mode | ||
|
||
def write_inquiry_mode(self,sock, mode): | ||
"""returns 0 on success, -1 on failure""" | ||
# save current filter | ||
old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) | ||
|
||
# Setup socket filter to receive only events related to the | ||
# write_inquiry_mode command | ||
flt = bluez.hci_filter_new() | ||
opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, | ||
bluez.OCF_WRITE_INQUIRY_MODE) | ||
bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) | ||
bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE) | ||
bluez.hci_filter_set_opcode(flt, opcode) | ||
sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt) | ||
|
||
# send the command! | ||
bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, | ||
bluez.OCF_WRITE_INQUIRY_MODE, struct.pack("B", mode)) | ||
|
||
pkt = sock.recv(255) | ||
|
||
status = struct.unpack("xxxxxxB", pkt)[0] | ||
|
||
# restore old filter | ||
sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, old_filter) | ||
if status != 0: return -1 | ||
return 0 | ||
|
||
def device_inquiry_with_with_rssi(self,sock): | ||
# save current filter | ||
old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) | ||
|
||
# perform a device inquiry on bluetooth device #0 | ||
# The inquiry should last 8 * 1.28 = 10.24 seconds | ||
# before the inquiry is performed, bluez should flush its cache of | ||
# previously discovered devices | ||
flt = bluez.hci_filter_new() | ||
bluez.hci_filter_all_events(flt) | ||
bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) | ||
sock.setsockopt(bluez.SOL_HCI, bluez.HCI_FILTER, flt) | ||
|
||
duration = 4 | ||
max_responses = 255 | ||
cmd_pkt = struct.pack("BBBBB", 0x33, 0x8b, 0x9e, duration, max_responses) | ||
bluez.hci_send_cmd(sock, bluez.OGF_LINK_CTL, bluez.OCF_INQUIRY, cmd_pkt) | ||
|
||
results = [] | ||
|
||
done = False | ||
while not done: | ||
pkt = sock.recv(255) | ||
ptype, event, plen = struct.unpack("BBB", pkt[:3]) | ||
if event == bluez.EVT_INQUIRY_RESULT_WITH_RSSI: | ||
pkt = pkt[3:] | ||
nrsp = bluetooth.get_byte(pkt[0]) | ||
for i in range(nrsp): | ||
addr = bluez.ba2str( pkt[1+6*i:1+6*i+6] ) | ||
rssi = bluetooth.byte_to_signed_int( | ||
bluetooth.get_byte(pkt[1+13*nrsp+i])) | ||
results.append((addr, rssi, str(datetime.datetime.utcnow()))) | ||
|
||
elif event == bluez.EVT_INQUIRY_COMPLETE: | ||
done = True | ||
elif event == bluez.EVT_CMD_STATUS: | ||
status, ncmd, opcode = struct.unpack("BBH", pkt[3:7]) | ||
if status != 0: | ||
print("uh oh...") | ||
self.printpacket(pkt[3:7]) | ||
done = True | ||
elif event == bluez.EVT_INQUIRY_RESULT: | ||
pkt = pkt[3:] | ||
nrsp = bluetooth.get_byte(pkt[0]) | ||
for i in range(nrsp): | ||
addr = bluez.ba2str(pkt[1+6*i:1+6*i+6]) | ||
results.append((addr, -1, str(datetime.datetime.utcnow()))) | ||
else: | ||
print("unrecognized packet type 0x%02x" % ptype) | ||
|
||
|
||
# restore old filter | ||
sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) | ||
|
||
return results | ||
|
||
def scan(self): | ||
# scan for bluetooth device names | ||
inquryResult = self.device_inquiry_with_with_rssi(self.sock) | ||
results = [] | ||
for device in inquryResult: | ||
name = bluetooth.lookup_name(device[0], 10) | ||
results.append({"mac": device[0], "rssi": device[1], "name": name, "ts": device[2]}) | ||
return results | ||
|
||
|
||
# testing the helper class and write results to btinquery.txt | ||
if __name__ == '__main__': | ||
inqurer = InqueryHelper() | ||
f = open("btinquery.txt","w") | ||
f.write('Bluetooth MAC;rssi;Name;time stamp UTC\r\n') | ||
f.close() | ||
|
||
while True: | ||
res = inqurer.scan() | ||
f = open("btinquery.txt", "a+") | ||
for dev in res: | ||
f.write(str(dev['mac']) +";"+ str(dev["rssi"])+';'+str(dev["name"])+';'+dev["ts"]+"\r\n") | ||
f.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#!/usr/bin/python3 | ||
import InqueryHelper | ||
import HTTPPostHelper | ||
import datetime | ||
import time | ||
import _thread | ||
import configparser | ||
|
||
|
||
config = configparser.ConfigParser() | ||
config.read('config.ini') | ||
|
||
#needed configurations read from config file | ||
postAddress = config['serverConfigurations']['postAddress'] | ||
id = config['GatewayConfiguration']['id'] | ||
name = config['GatewayConfiguration']['name'] | ||
interval = int(config['GatewayConfiguration']['PostInterval']) | ||
|
||
# shared list used to exchange Beacon scans with post thread | ||
returnedList =[] | ||
|
||
ScanThreat = InqueryHelper.InqueryHelper(0) | ||
HttpPostThreat = HTTPPostHelper.HTTPPostHelper(id, name,postAddress) | ||
|
||
def scanProcess(): | ||
while True: | ||
returnedList.extend(ScanThreat.scan()) | ||
|
||
def postProcess(): | ||
while True: | ||
#temporary list used for exchange | ||
templist = returnedList.copy() | ||
returnedList.clear() | ||
try: | ||
HttpPostThreat.startPosting(templist) | ||
except: | ||
print('couldnt post data') | ||
time.sleep(interval) | ||
|
||
|
||
try: | ||
_thread.start_new_thread(scanProcess, ()) | ||
_thread.start_new_thread(postProcess, ()) | ||
except: | ||
print ("Error: unable to start thread") | ||
|
||
while True: | ||
pass |
Oops, something went wrong.