import paho.mqtt.client as mqtt import json import base64 import message_pb2 import sqlite3 import time import configparser config = configparser.ConfigParser() config.read("config.ini") app_id = config['Default']['AppId'] access_key = config['Default']['AccessKey'] # For now use collar id of 1, should look up collar id based on collarname from db def store_collar_data(collarname, res): print("Coord {x: " + str(res.loc.x) + ", y: " + str(res.loc.y) + "}") db = sqlite3.connect('data.sqlite') entries = [(1, res.loc.y, res.loc.x)] db.executemany( "INSERT INTO data_point (collar_id, longitude, latitude, datetime) VALUES (?,?,?,datetime('now'))", entries) db.commit() if(res.oob == 1): entries = [(1, res.loc.y, res.loc.x)] db.executemany( "INSERT INTO stimulus_activation (collar_id, longitude, latitude, datetime) VALUES (?,?,?,datetime('now'))", entries) db.commit() db.close() def boundary_get_coord(self, key): if key == 0: return self.coord0 if key == 1: return self.coord1 if key == 2: return self.coord2 if key == 3: return self.coord3 if key == 4: return self.coord4 if key == 5: return self.coord5 if key == 6: return self.coord6 if key == 7: return self.coord7 if key == 8: return self.coord8 if key == 9: return self.coord9 message_pb2.Coordinates.__getitem__ = boundary_get_coord def pack_boundary(boundary): coordinates = message_pb2.Coordinates() coordinates.isr = boundary[2] for i in range(boundary[2]): coordinates[i].x = boundary[4 + 2*i] coordinates[i].y = boundary[5 + 2*i] for i in range(boundary[2], 10): coordinates[i].x = 1.0 coordinates[i].y = 1.0 return coordinates def push_coordinate(id, packed): payload = { 'port': 1, 'confirmed': False, 'payload_raw': base64.b64encode(packed.SerializeToString()) } print("Pushing coordinate", packed) print("Device ID:", id) print("Payload:", json.dumps(payload)) client.publish(app_id+"/devices/" + 'fenceless' + "/down", json.dumps(payload)) def find_new_boundaries(): db = sqlite3.connect('data.sqlite') bounds = db.execute("SELECT * from bounding_box where needs_push=1").fetchall() for bound in bounds: print("Found boundary. ID:", bound[0]) push_coordinate(bound[1], pack_boundary(bound)) db.execute("UPDATE bounding_box set needs_push=0 where id=?", (bound[0],)) db.commit() connected = False # The callback for when the client receives a CONNACK response from the server. def on_connect(client, userdata, flags, rc): global connected connected = True print("Connected with result code "+str(rc)) # Subscribing in on_connect() means that if we lose the connection and # reconnect then subscriptions will be renewed. # client.subscribe("+/devices/+/events/activations") client.subscribe("+/devices/+/up") client.publish(app_id+"/devices/+/down", "hello world") # The callback for when a PUBLISH message is received from the server. def on_message(client, userdata, msg): # Print entire payload print(msg.payload) # Parse payload (JSON) payload = json.loads(msg.payload) # Decode payload_raw, which is the protobuf code = payload['payload_raw'] bcode = base64.b64decode(code) res = message_pb2.CollarResponse() res.ParseFromString(bcode) # store_collar_data(payload['dev_id'], res.loc.x, res.loc.y) store_collar_data(payload['dev_id'], res) coordinates = message_pb2.Coordinates() coordinates.isr = 4 coordinates.coord0.x = 0 coordinates.coord1.x = 1 coordinates.coord2.x = 0 coordinates.coord3.x = 1 coordinates.coord0.y = 1 coordinates.coord1.y = 1 coordinates.coord2.y = 0 coordinates.coord3.y = 0 # coordinates.coord0.x = 44.5934295644297 # coordinates.coord1.x = 44.5934295644297 # coordinates.coord2.x = 44.5934295664297 # coordinates.coord3.x = 44.5934295664297 # # coordinates.coord0.y = -123.306968698965 # coordinates.coord1.y = -123.306968678965 # coordinates.coord2.y = -123.306968678965 # coordinates.coord3.y = -123.306968698965 coordinates.coord4.x = 1 coordinates.coord5.x = 1 coordinates.coord6.x = 1 coordinates.coord7.x = 1 coordinates.coord8.x = 1 coordinates.coord9.x = 1 coordinates.coord4.y = 2 coordinates.coord5.y = 2 coordinates.coord6.y = 2 coordinates.coord7.y = 2 coordinates.coord8.y = 2 coordinates.coord9.y = 2 # SerializeToString() print(base64.b64encode(coordinates.SerializeToString())) client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.username_pw_set(app_id, access_key) client.connect("us-west.thethings.network", 1883, 60) # Blocking call that processes network traffic, dispatches callbacks and # handles reconnecting. # Other loop*() functions are available that give a threaded interface and a # manual interface. client.loop_start() while not connected: time.sleep(0.1) print("Starting boundary checking work.") while True: find_new_boundaries() time.sleep(10)