|
|
|
@ -72,96 +72,36 @@ class MessageDbService(MultiDeviceDbSupport): |
|
|
|
c = collection.find(payload).sort("ts", DESCENDING).skip(offset).limit(limit) |
|
|
|
return await c.to_list() |
|
|
|
|
|
|
|
class NodeDbService(MultiDeviceDbSupport): |
|
|
|
class PacketDbService(MultiDeviceDbSupport): |
|
|
|
def __init__(self, dbStore, core): |
|
|
|
super().__init__(dbStore, core) |
|
|
|
|
|
|
|
async def listOfNodes(self, devices = []): |
|
|
|
pipeline = [ #ai slooop |
|
|
|
{"$match": {"$or": self.deviceHash2Match(devices)}}, |
|
|
|
# Сортировка для каждого num по убыванию ts |
|
|
|
{"$sort": {"num": 1, "ts": -1}}, |
|
|
|
# Группировка по num и взятие первого (последнего) документа |
|
|
|
{"$group": { |
|
|
|
"_id": "$num", |
|
|
|
"latest_doc": {"$first": "$$ROOT"} |
|
|
|
}}, |
|
|
|
# Замена корневого документа |
|
|
|
{"$replaceRoot": {"newRoot": "$latest_doc"}}, |
|
|
|
# Сортировка результата (опционально) |
|
|
|
{"$sort": {"num": 1}} |
|
|
|
] |
|
|
|
async def findLastPackets(self, nums: List[int] = [], portnums: List[int] = []): |
|
|
|
pipeline = [] |
|
|
|
match = {} |
|
|
|
|
|
|
|
collection = self.dbStore['node_info'] |
|
|
|
c = await collection.aggregate(pipeline) |
|
|
|
return await c.to_list() |
|
|
|
|
|
|
|
async def listOfDirectNodes(self, devices = []): |
|
|
|
pipeline = [ #ai slooop |
|
|
|
{"$match": {"hops_away": 0, "$or": self.deviceHash2Match(devices)}}, # Фильтруем по списку |
|
|
|
# Сортировка для каждого num по убыванию ts |
|
|
|
{"$sort": {"num": 1, "ts": -1}}, |
|
|
|
# Группировка по num и взятие первого (последнего) документа |
|
|
|
if nums: |
|
|
|
match["from"] = {"$in": nums} |
|
|
|
|
|
|
|
if portnums: |
|
|
|
match["portnum"] = {"$in": portnums} |
|
|
|
|
|
|
|
if match: |
|
|
|
pipeline += [{"$match":match}] |
|
|
|
|
|
|
|
pipeline += [ |
|
|
|
{"$sort": {"from": 1, "ts": -1}}, |
|
|
|
{"$group": { |
|
|
|
"_id": "$num", |
|
|
|
"_id": "$from", |
|
|
|
"latest_doc": {"$first": "$$ROOT"} |
|
|
|
}}, |
|
|
|
# Замена корневого документа |
|
|
|
{"$replaceRoot": {"newRoot": "$latest_doc"}}, |
|
|
|
# Сортировка результата (опционально) |
|
|
|
{"$sort": {"num": 1}} |
|
|
|
] |
|
|
|
|
|
|
|
collection = self.dbStore['node_info'] |
|
|
|
c = await collection.aggregate(pipeline) |
|
|
|
return await c.to_list() |
|
|
|
|
|
|
|
async def oneNode(self, num: int, devices = []): |
|
|
|
collection = self.dbStore['node_info'] |
|
|
|
c = await collection.find_one( |
|
|
|
{"num":int(num), "$or": self.deviceHash2Match(devices)}, |
|
|
|
sort=[("ts", -1)] |
|
|
|
) |
|
|
|
return c |
|
|
|
|
|
|
|
async def listOfSelectedNodes(self, nums: List[int], devices = []): |
|
|
|
pipeline = [ |
|
|
|
{"$match": {"num": {"$in": nums}, "$or": self.deviceHash2Match(devices)}}, # Фильтруем по списку |
|
|
|
{"$sort": {"num": 1, "ts": -1}}, # Сортируем по num и ts (по убыванию) |
|
|
|
{ |
|
|
|
"$group": { |
|
|
|
"_id": "$num", # Группируем по num |
|
|
|
"latest_doc": {"$first": "$$ROOT"} # Берем первую (последнюю по ts) |
|
|
|
} |
|
|
|
}, |
|
|
|
{"$replaceRoot": {"newRoot": "$latest_doc"}}, # Восстанавливаем структуру |
|
|
|
{"$sort": {"num": 1}} # Сортируем результат по num |
|
|
|
] |
|
|
|
collection = self.dbStore['node_info'] |
|
|
|
c = await collection.aggregate(pipeline) |
|
|
|
return await c.to_list() |
|
|
|
|
|
|
|
async def listOfFindLikeName(self, long_name, devices = []): |
|
|
|
pipeline = [ |
|
|
|
{"$match": {"long_name": {"$regex":long_name ,'$options' : 'i'}, "$or": self.deviceHash2Match(devices)}}, # Фильтруем по списку |
|
|
|
{"$sort": {"num": 1, "ts": -1}}, # Сортируем по num и ts (по убыванию) |
|
|
|
{ |
|
|
|
"$group": { |
|
|
|
"_id": "$num", # Группируем по num |
|
|
|
"latest_doc": {"$first": "$$ROOT"} # Берем первую (последнюю по ts) |
|
|
|
} |
|
|
|
}, |
|
|
|
{"$replaceRoot": {"newRoot": "$latest_doc"}}, # Восстанавливаем структуру |
|
|
|
{"$sort": {"num": 1}} # Сортируем результат по num |
|
|
|
{"$sort": {"from": 1}} |
|
|
|
] |
|
|
|
collection = self.dbStore['node_info'] |
|
|
|
collection = self.dbStore['packet'] |
|
|
|
c = await collection.aggregate(pipeline) |
|
|
|
return await c.to_list() |
|
|
|
|
|
|
|
class PacketDbService(MultiDeviceDbSupport): |
|
|
|
def __init__(self, dbStore, core): |
|
|
|
super().__init__(dbStore, core) |
|
|
|
|
|
|
|
async def findPacketsSignals(self, |
|
|
|
after: float = -1, |
|
|
|
before: float = -1, |
|
|
|
@ -248,6 +188,145 @@ class PacketDbService(MultiDeviceDbSupport): |
|
|
|
c = await collection.aggregate(pipeline) |
|
|
|
l = await c.to_list() |
|
|
|
return [PacketGroup(p, packetsPerNode, packetsSumNode) for p in l] |
|
|
|
|
|
|
|
class NodeDbService(PacketDbService, MultiDeviceDbSupport): |
|
|
|
def __init__(self, dbStore, core): |
|
|
|
PacketDbService.__init__(self, dbStore, core) |
|
|
|
MultiDeviceDbSupport.__init__(self, dbStore, core) |
|
|
|
|
|
|
|
async def fillNodeFromPacketCollection(self, l): |
|
|
|
nums = [node.get("num", 0) for node in l] |
|
|
|
|
|
|
|
#ищем сначала ноды с позицией 3 портнум |
|
|
|
packet_pos_nodes = await self.findLastPackets(nums, [3])#### |
|
|
|
packet_pos_nodes_dict = {}### |
|
|
|
for packet in packet_pos_nodes: |
|
|
|
packet_pos_nodes_dict[packet.get("from")] = packet |
|
|
|
nums_with_pos = [node.get("from", 0) for node in packet_pos_nodes] |
|
|
|
|
|
|
|
#смотрим какие пакеты от нод имеют позицию, и делаем список нод где нет ее |
|
|
|
nums_without_pos = [fr0m for fr0m in nums if fr0m not in nums_with_pos] |
|
|
|
packet_without_pos = await self.findLastPackets(nums_without_pos, [])#### |
|
|
|
packet_without_pos_dict = {} |
|
|
|
for packet in packet_without_pos: |
|
|
|
packet_without_pos_dict[packet.get("from")] = packet |
|
|
|
|
|
|
|
#суем свежачок |
|
|
|
new_nodes_list = [] |
|
|
|
def fillNodeBaseData(node, d1ct): |
|
|
|
## base packet |
|
|
|
if d1ct[node["num"]].get("rx_snr", None) != None: |
|
|
|
node["snr"] = d1ct[node["num"]]["rx_snr"] |
|
|
|
if d1ct[node["num"]].get("rx_rssi", None) != None: |
|
|
|
node["rssi"] = d1ct[node["num"]]["rx_rssi"] |
|
|
|
if d1ct[node["num"]].get("ts", None) != None: |
|
|
|
node["ts"] = d1ct[node["num"]]["ts"] |
|
|
|
if d1ct[node["num"]].get("hop_start", None) != None and d1ct[node["num"]].get("hop_limit", None) != None: |
|
|
|
node["hops_away"] = d1ct[node["num"]].get("hop_start", 0) - d1ct[node["num"]].get("hop_limit", 0) |
|
|
|
if d1ct[node["num"]].get("portnum", None) != None: |
|
|
|
node["last_portnum"] = d1ct[node["num"]].get("portnum", None) |
|
|
|
return node |
|
|
|
|
|
|
|
for node in l: |
|
|
|
node["view_in_packets"] = True |
|
|
|
if node.get("num", 0) in packet_pos_nodes_dict.keys(): |
|
|
|
if packet_pos_nodes_dict[node["num"]].get("decoded_payload_object", {}): |
|
|
|
node["position"] = packet_pos_nodes_dict[node["num"]]["decoded_payload_object"] |
|
|
|
|
|
|
|
node = fillNodeBaseData(node, packet_pos_nodes_dict) |
|
|
|
elif node.get("num", 0) in packet_without_pos_dict.keys(): |
|
|
|
node = fillNodeBaseData(node, packet_without_pos_dict) |
|
|
|
else: |
|
|
|
node["view_in_packets"] = False |
|
|
|
|
|
|
|
new_nodes_list.append(node) |
|
|
|
|
|
|
|
return new_nodes_list |
|
|
|
|
|
|
|
async def listOfNodes(self, devices = []): |
|
|
|
pipeline = [ #ai slooop |
|
|
|
{"$match": {"$or": self.deviceHash2Match(devices)}}, |
|
|
|
# Сортировка для каждого num по убыванию ts |
|
|
|
{"$sort": {"num": 1, "ts": -1}}, |
|
|
|
# Группировка по num и взятие первого (последнего) документа |
|
|
|
{"$group": { |
|
|
|
"_id": "$num", |
|
|
|
"latest_doc": {"$first": "$$ROOT"} |
|
|
|
}}, |
|
|
|
# Замена корневого документа |
|
|
|
{"$replaceRoot": {"newRoot": "$latest_doc"}}, |
|
|
|
# Сортировка результата (опционально) |
|
|
|
{"$sort": {"num": 1}} |
|
|
|
] |
|
|
|
|
|
|
|
collection = self.dbStore['node_info'] |
|
|
|
c = await collection.aggregate(pipeline) |
|
|
|
l = await c.to_list() |
|
|
|
return await self.fillNodeFromPacketCollection(l) |
|
|
|
|
|
|
|
async def listOfDirectNodes(self, devices = []): |
|
|
|
pipeline = [ #ai slooop |
|
|
|
{"$match": {"hops_away": 0, "$or": self.deviceHash2Match(devices)}}, # Фильтруем по списку |
|
|
|
# Сортировка для каждого num по убыванию ts |
|
|
|
{"$sort": {"num": 1, "ts": -1}}, |
|
|
|
# Группировка по num и взятие первого (последнего) документа |
|
|
|
{"$group": { |
|
|
|
"_id": "$num", |
|
|
|
"latest_doc": {"$first": "$$ROOT"} |
|
|
|
}}, |
|
|
|
# Замена корневого документа |
|
|
|
{"$replaceRoot": {"newRoot": "$latest_doc"}}, |
|
|
|
# Сортировка результата (опционально) |
|
|
|
{"$sort": {"num": 1}} |
|
|
|
] |
|
|
|
|
|
|
|
collection = self.dbStore['node_info'] |
|
|
|
c = await collection.aggregate(pipeline) |
|
|
|
l = await c.to_list() |
|
|
|
return await self.fillNodeFromPacketCollection(l) |
|
|
|
|
|
|
|
async def oneNode(self, num: int, devices = []): |
|
|
|
collection = self.dbStore['node_info'] |
|
|
|
c = await collection.find_one( |
|
|
|
{"num":int(num), "$or": self.deviceHash2Match(devices)}, |
|
|
|
sort=[("ts", -1)] |
|
|
|
) |
|
|
|
return await self.fillNodeFromPacketCollection([c]) |
|
|
|
|
|
|
|
async def listOfSelectedNodes(self, nums: List[int], devices = []): |
|
|
|
pipeline = [ |
|
|
|
{"$match": {"num": {"$in": nums}, "$or": self.deviceHash2Match(devices)}}, # Фильтруем по списку |
|
|
|
{"$sort": {"num": 1, "ts": -1}}, # Сортируем по num и ts (по убыванию) |
|
|
|
{ |
|
|
|
"$group": { |
|
|
|
"_id": "$num", # Группируем по num |
|
|
|
"latest_doc": {"$first": "$$ROOT"} # Берем первую (последнюю по ts) |
|
|
|
} |
|
|
|
}, |
|
|
|
{"$replaceRoot": {"newRoot": "$latest_doc"}}, # Восстанавливаем структуру |
|
|
|
{"$sort": {"num": 1}} # Сортируем результат по num |
|
|
|
] |
|
|
|
collection = self.dbStore['node_info'] |
|
|
|
c = await collection.aggregate(pipeline) |
|
|
|
l = await c.to_list() |
|
|
|
return await self.fillNodeFromPacketCollection(l) |
|
|
|
|
|
|
|
async def listOfFindLikeName(self, long_name, devices = []): |
|
|
|
pipeline = [ |
|
|
|
{"$match": {"long_name": {"$regex":long_name ,'$options' : 'i'}, "$or": self.deviceHash2Match(devices)}}, # Фильтруем по списку |
|
|
|
{"$sort": {"num": 1, "ts": -1}}, # Сортируем по num и ts (по убыванию) |
|
|
|
{ |
|
|
|
"$group": { |
|
|
|
"_id": "$num", # Группируем по num |
|
|
|
"latest_doc": {"$first": "$$ROOT"} # Берем первую (последнюю по ts) |
|
|
|
} |
|
|
|
}, |
|
|
|
{"$replaceRoot": {"newRoot": "$latest_doc"}}, # Восстанавливаем структуру |
|
|
|
{"$sort": {"num": 1}} # Сортируем результат по num |
|
|
|
] |
|
|
|
collection = self.dbStore['node_info'] |
|
|
|
c = await collection.aggregate(pipeline) |
|
|
|
return await c.to_list() #no need fill, just search |
|
|
|
|
|
|
|
class DbService(NodeDbService, PacketDbService, MessageDbService): |
|
|
|
def __init__(self, dbStore, core): |
|
|
|
|