How can I force a coap server node to connect an specific border router? - contiki

force nodes to connect to specific border router in a mesh network
Here is my setup;
6 nodes, n1, n2, n3, n4, n5, n6 all running https://github.com/contiki-os/contiki/blob/master/examples/er-rest-example/er-example-server.c Coap server
2 border router, b1, b2 running https://github.com/contiki-os/contiki/tree/master/examples/ipv6/rpl-border-router connected to two Linux board (like Raspberry Pi) L1, L2.
How can I make sure that n1, n2, n3 node only connect to border router b1 and not b2, similarily, n4, n5, n6 nodes only connect to border router b2 and not b1? Thanks!

Need to change panid;
use for boarder-router b1, n1, n2, n3 panid 0xabcd
use for boarder-router b2, n4, n5, n6 panid 0xabce
*Thanks to Harald Pichler (Contiki mailing list) for this answer

Related

Cypher Connect nodes in a path returned by gds.alpha.kShortestPaths.stream

I run gds.alpha.kShortestPaths.stream using Neo4j 4.0.2. The algorithm yields a path.
The path has the nodes connected with NEXT relationship. I need to find the actual relationships in the Graph that connect the nodes in the path. I came up with a kludgy query that is based on my knowing how long the path is:
...
YIELD path
with nodes(path) as nodes with nodes[0] as n0, nodes[1] as n1, nodes[2] as n2, nodes[3] as n3
match (n0)-[r1]-(n1)
match (n1)-[r2]-(n2)
match (n2)-[r3]-(n3)
return n0, n1, n2, n3, r1, r2, r3
Obviously this solution is inadequate and the only reason I posted it here is to illustrate what I need to do for a path of any length.
Thank you
You can do this programmatically with:
YIELD index, path
WITH index, nodes(path) as nodes
WITH index, nodes, size(nodes) as number_of_nodes
UNWIND range(0,number_of_nodes - 2) as start
WITH index, nodes[start] as start_node, nodes[start + 1] as end_node
MATCH (start_node)-[r:NEXT]->(end_node)
RETURN index, start_node,r, end_node

Neo4j: How to fix one of the node in match clause?

For clauses like MATCH (a:Address)-[:BelongTo]->(w1:Wallet), (a)-[r0:BelongTo]->(w2:Wallet) WHERE ID(w1)>ID(w2) WITH w1, w2..., is it possible to make sure that ex. w1 is always a fixed node? If yes, is it possible to decide on the node by choosing the node having ex. the minimum value for a certain property over all the nodes which could also be w1?
More concretely, for example, an address a belong to wallet a, b, c with a>b>c in terms of ID. Then normally these rows of result will be returned:
w1 w2
--------
a b
b c
a c
I only want these two rows of result to be returned:
w1 w2
--------
a b
a c
Note: I want the query try to get every pair of wallets to both an address belongs to. All addresses which belongs to two or more wallet should be included in return if a is returned.
So for example, If there are two addresses which belong to three different wallets, what would the query you posted do?
More concretely, if addresses a1 and a2 belong to b1, c1, d1 and b2, c2, d2 respectively, (with b1 > c1 > d1> b2> c2>d2 in terms of id)
I want it to return:
a w1 w2
-----------
a1 b1 c1
a1 b1 d1
a2 b2 c2
a2 b2 d2
Is it possible?
Yes, you can do this by finding (for each a:Address), the :Wallet with the minimum id. After you match to this :Wallet, you can match to all the other :Wallets.
MATCH (a:Address)-[:BelongTo]->(w1:Wallet)
WITH a, min(id(w1)) as minId
// since we have the minId, we can do a fast lookup of the node
MATCH (minW:Wallet)
WHERE id(minW) = minId
// now get all the others
MATCH (a)-[:BelongTo]->(w2:Wallet)
WHERE minW <> w2
...
If you don't care how the fixed node is taken, and if it only matters for the duration of the query, it may be easier to collect all the :Wallet nodes, take the first node in the collection, and then UNWIND the rest into rows and continue the query:
MATCH (a:Address)-[:BelongTo]->(w:Wallet)
WITH a, collect(w) as wallets
WITH a, head(wallets) as w1, wallets
UNWIND tail(wallets) as w2
...

Cypher: extract only nodes with independent connections to two other nodes?

I have the following query:
MATCH (rebecca:Person)-[r1*1..3]-(robert:Person)
WHERE rebecca.name=Rebecca AND robert.name='Robert'
RETURN rebecca, robert,
extract(x IN r1 | {rel: x, start: startNode(x), end: endNode(x)})
This returns all the nodes and edges within 3 hops of both Rebecca or Robert. So it includes some nodes that are 2 hops from Rebecca, and 3 hops from Robert, where his connection is via Rebecca.
Is there a way I can exclude the nodes for which Robert's only connection is via Rebecca, and vice versa?
I'm interested in connections that they truly share independently, not where the only connection is via each other.
With 3 hops, the only possible way to go through the other is if (from Rebecca for this example):
rebecca->robert->node->robert
So robert would have to appear twice (or rebecca, from the other direction).
It seems to me that you just need a restriction that rebecca and robert must appear only once each in the path:
MATCH p=(rebecca:Person)-[r1*1..3]-(robert:Person)
WHERE rebecca.name=Rebecca AND robert.name='Robert'
AND SINGLE(rebecca in nodes(p)) AND SINGLE(robert in nodes(p))
RETURN rebecca, robert,
extract(x IN r1 | {rel: x, start: startNode(x), end: endNode(x)})

Neo4j Cypher path using several times the same edge

Let us consider a simple example with two types of nodes: Company and Worker. For any couple of companies c1 and c2 (which respect some conditions that I will ignore here), I'd need to know: 1. How many workers they have in common, how many workers has c1, and how many workers has c2.
My first guess was :
MATCH (w_c1:Worker)--(c1:Company)--(w_common)--(c2:Company)--(w_c2:Worker)
WHERE <something>
RETURN c1, c2, COUNT(DISTINCT w_common), COUNT(DISTINCT w_c1), COUNT(DISTINCT w_c1)
The problem with that request is that, if I have only one link between any pair of connected nodes, COUNT(DISTINCT w_c1) (id for w_c2) does only count the worker of c1 which are not common with c2. But if I have several relations between some nodes, the results is sometimes "correct". It sounds like the path in the match does not "come back" : (w_common)--(c2:Company)--(w_c2:Worker) will no match ("worker1")--("company2")--("worker1") (which may make sense to avoid infinite loops).
My second guess was to split the request in two parts:
My first guess was :
MATCH (c1:Company)--(w_common)--(c2:Company)
MATCH (c1)--(w_c1:Worker), (c2)--(w_c2:Worker)
WHERE <something>
RETURN c1, c2, COUNT(DISTINCT w_common), COUNT(DISTINCT w_c1), COUNT(DISTINCT w_c1)
But then, the results is correct but I have a warning about cartesian products, and indeed, on big dataset, my request does not complete after hours. I tried with a "WITH c1, w_common, c2" between the two matches, but I still have the warning
How should I proceed ?
One thing that will help you is the SIZE() function, which can tell you the number of occurrences of a pattern, such as the number of :Workers per :Company.
This query may work for you, assuming that a Worker working for a Company only has one relationship to that Company:
MATCH (c1:Company)--(w_common:Worker)--(c2:Company)
WHERE <your criteria for matching on a specific c1 and c2>
RETURN COUNT(w_common) as inCommonCount, SIZE( (c1)--(:Worker) ) as c1Count, SIZE( (c2)--(:Worker) ) as c2Count
You can use sub-totals:
OPTIONAL MATCH (C1:Company {name: 'c1'})
OPTIONAL MATCH (C2:Company {name: 'c2'})
WITH C1, C2
MATCH (C:Company)<-[:workto]-(W:Worker) WHERE C = C1 OR C = C2
WITH C1, C2, W,
sum(CASE WHEN C = C1 THEN 1 ELSE 0 END) as tmp1,
sum(CASE WHEN C = C2 THEN 1 ELSE 0 END) as tmp2
RETURN C1, C2,
sum(tmp1) as cc1, sum(tmp2) as cc2,
sum(tmp1 * tmp2 ) as common

Get nodes connected only to other nodes that have a property in a range

I have 4 types of nodes: S, G, R and C
S nodes have an idStr property that identifies them.
Every node of type G uses just a S node: (:G)-[:USES]->(:S)
Every node of type C may be connected to multiple R or G nodes: (:C)-[:CONNECTED_TO]->(:R|:G)
Every node of type R may be connected to multiple R or G nodes: (:R)-[:CONNECTED_TO]->(:R|:G)
Question:
Given an idStr range, I want to get all R and C nodes that are connected (directly or indirectly) only to G nodes that use S nodes with an idStr in that range.
The closest approach I have achieved is:
MATCH (a:S)<-[:USES]-(b:G)<-[:CONNECTED_TO*]-(n:C)
WHERE a.idStr IN ['1a','b2','something']
WITH COLLECT(DISTINCT b) AS GroupGs
MATCH p=(n)-[:CONNECTED_TO*]->(c:G)
WITH FILTER(x IN NODES(p) WHERE NOT x:G) AS cs,GroupGs,COLLECT(c) AS gs
WHERE ALL(x IN gs WHERE x IN GroupGs)
RETURN cs
but still some nodes that are connected to G nodes that use S nodes not in the range are being returned. [Neo4j Console Test]
What am I trying to do?
First match is used to get two things: G nodes that use S nodes with idStr in the given range (GroupGs) and the C nodes that are connected to those G nodes.
Once we get that, we have to check if those C nodes are connected to more G nodes (directly or through R nodes). That is the second match.
Now we have to check for each C node if all the G nodes connected to it (directly or through R nodes) are in the GroupGs range. If it is so, that C node (and the R nodes in the paths to the G nodes) are a match, and that is what I am trying to get.
Second approach (suggested by #FrobberOfBits)
Trying to use just one match, so we are sure the n node is the same in the matching:
MATCH (a:S)<-[:USES]-(b:G)<-[:CONNECTED_TO*]-(n:C), p=(n)-[:CONNECTED_TO*]->(c:G)
WHERE a.idStr IN ['1a','b2','something']
WITH COLLECT(DISTINCT b) AS GroupGs, FILTER(x IN NODES(p) WHERE NOT x:G) AS cs,COLLECT(c) AS gs
WHERE ALL(x IN gs WHERE x IN GroupGs)
RETURN cs
The result is the same. [Neo4j Console Test]
Third approach (suggested by #FrobberOfBits)
Giving semantics to the problem, C may be an endpoint in a network, R a repeater, G a gateway and S a Sim card.
Sim nodes have an iccid property that identifies them.
Every node of type Gateway uses just a Sim node: (:Gateway)-[:USES]->(:Sim)
Every node of type Endpoint may be connected to multiple Repeater or Gateway nodes: (:Endpoint)-[:CONNECTED_TO]->(:Repeater|:Gateway)
Every node of type Repeater may be connected to multiple Repeater or Gateway nodes: (:Repeater)-[:CONNECTED_TO]->(:Repeater|:Gateway)
I am trying to get all the Repeater and Endpoint nodes that are just connected to Gateway nodes that are using Sim nodes whose iccid are in a range.
Any idea about what am I doing wrong?
Your query is really confusing things with the variables you choose -- binding "a" to label S's, and "b" to label G's? Later binding "c" to "G's" in the second match clause? This query is going to be hard to debug in the future, and makes it hard to see what's going on; consider binding label "G" to "g", or "gs", or similar, and so on.
I think your problem is the second match clause. The (c:G) in the second match clause doesn't relate to anything in the first (which is (b:G)). This means that the path via a set of CONNECTED_TO* relationships from some node to some (c:G) has nothing to do with the complex match on the first line of the query. This second match matches anything labeled G, not just the things you specify in the first match.
That second match is bad because of the requirement you stated:
only to G nodes that use S nodes with an idStr in that range
I don't have your test data, so I can't verify that this works. But here's something to try instead:
MATCH (a:S)<-[:USES]-(b:G)<-[:CONNECTED_TO*]-(n:C),
p=(n)-[:CONNECTED_TO*]->(b:G)
WHERE a.idStr IN ['1a','b2','something']
WITH COLLECT(DISTINCT b) AS GroupGs,
FILTER(x IN NODES(p) WHERE NOT x:G) AS cs,GroupGs,COLLECT(c) AS gs
WHERE ALL(x IN gs WHERE x IN GroupGs)
RETURN cs
Apologies if the syntax edited here isn't perfect; this is a complex query and is going to take some fiddling, but I think the placement and mis-labeling of that second MATCH is your issue. My solution may not be perfect and may require tinkering, but should get you there.
I think I finally got it:
MATCH (a:S)<-[:USES]-(b:G)
WHERE a.idStr IN ['1a','b2','something']
WITH COLLECT(b) AS GroupGs
MATCH (c)-[:CONNECTED_TO*]->(d:G)
WHERE NOT d IN GroupGs
WITH COLLECT(c) AS badCandidates,GroupGs
MATCH (e)-[:CONNECTED_TO*]->(f:G)
WHERE NOT e IN badCandidates AND f IN GroupGs
RETURN e
First I get GroupGs: all the G nodes that use a S node with an idStr property in the given range.
Now I collect all the C and R nodes that are connected to a G node not in the GroupGs and I call them badCandidates.
Finally, I get all the C and R nodes that are not in the badCandidates collection and are connected to a G node in the GroupGs.
Here you have an example: [Neo4j Console Test]
I hope this helps someone.

Resources