So, I've got a Zwave stick, and a raspberry pi, and I'd like to have OZWCP running on it to help with troubleshooting, etc.

But last time I tried, it was showing the zwave stick as being the Primary controller, and I couldn't figure out if Hubitat agreed or disagreed. Is anyone doing something like this reliably long term?

Really trying to just figure out slow repeaters, possibly bad repeaters, or just holes in the mesh.


I've been using that combo for slightly more than a year but NOT 24x7

I plug in the stick and start OZWCP on a rPi as needed. Pretty rarely these days... my migration days are over, I hope... unless I just have to have another HE to keep up with the Jones and Whites.

Because I have two Hubitat Hubs I have two ZWave networks. I 'clone' one onto the Aeon ZStick and then do a backup to disk. Then I reset the Aeon ZStick and 'clone' the other hub... ending with a backup to disk.

Yes, OZWCP GUI does show the stick as Primary, yet the logs clearly say it's not.


I have a script that I modified when I was using HomeAssistant to quantify the OZW_Log and the zwcfg xml file. The script shows neighbors and hops. I hadn't used this in a while but I ran it against the files I collected with OZWCP today and it generates the list.

if($argc !== 3) {
	die("Usage: {$argv[0]} OZW.log zwcfg.xml \n");
$ozwLog = $argv[1];
$zwcfg = $argv[2];
#$imageFilename= $argv[3];
$controllerId = 1;

$nodes = array();

echo "Reading XML\n";
if(FALSE) {	//  For debug when not having the xml file, should normally be FALSE
	$fixed = array(1,2,3,4,5,6,9,10,13,15,17,18,19,20,21);
	foreach($fixed as $n) {
		$nodes[$n]['name'] = $n;
} else {
	$xml = file_get_contents($zwcfg);
	$xml = new SimpleXMLElement($xml);
	foreach($xml->Node as $v) {
		$id = (int) $v['id'];
		$name = $v['name'];
		$name = reset($name);	// No clue why I get an array back

		if(empty($name)) {
			$name = "{$v->Manufacturer['name']} {$v->Manufacturer->Product['name']}";
		echo "{$id} => {$name}\n";

		$nodes[$id]['name'] = $name;

2017-10-14 12:02:31.336 Info, Node001,     Neighbors of this node are:
2017-10-14 12:02:31.336 Info, Node001,     Node 2
2017-10-14 12:02:31.336 Info, Node001,     Node 3
echo "Reading OZW log\n";
$buf = file_get_contents($ozwLog);
$buf = explode(PHP_EOL, $buf);
foreach($buf as $line) {

	if(preg_match('/.*Info, Node([0-9]{3}), +Neighbors of this node are:$/', $line, $matches) === 1) {
		$node = (int) $matches[1];

		echo $line . PHP_EOL;

		if(!isset($nodes[$node])) {
			die("Node {$node} not found in xml\n");

		$nodes[$node]['neighbors'] = array();
	else if(preg_match('/.*Info, Node([0-9]{3}), +Node ([0-9]+)$/', $line, $matches) === 1) {
		$node = (int) $matches[1];
		$neighbor = (int) $matches[2];
		echo $line . PHP_EOL;

		if(!isset($nodes[$node])) {
			die("Node {$node} not initialized\n");
		if(!isset($nodes[$node]['neighbors'])) {
			echo "WARNING: {$node} -> {$neighbor} listed before a list header, ignoring\n";

		if(!in_array($neighbor, $nodes[$node]['neighbors'])) {
			$nodes[$node]['neighbors'][] = $neighbor;

echo "Calculating hops\n";
$nodes[$controllerId]['hops'] = 0;	// The controller obviously has 0 hops
// Z-wave supports max 4 hops
for($maxHops = 1 ; $maxHops <= 4 ; $maxHops++) {
	foreach($nodes as $id => $n) {
		if(isset($n['hops'])) {

		if(!isset($n['neighbors'])) {	// Should not happen, this is a workaround
			echo "  WARNING: Node {$id} has no neighbors\n";
			$nodes[$id]['hops'] = 5;

		$hops = FALSE;
		foreach($n['neighbors'] as $neighbor) {
			if(!isset($nodes[$neighbor]['hops'])) {
			if($hops === FALSE || $nodes[$neighbor]['hops']+1 < $hops) {
				$hops = $nodes[$neighbor]['hops']+1;
		if($hops !== FALSE && $hops <= $maxHops) {
			$nodes[$id]['hops'] = $hops;
			echo "  $id  has {$hops} hops to the controller\n";

// Set hops to FALSE for nodes without neighbors
foreach($nodes as $id => $n) {
	if(isset($nodes[$id]['hops']) && $nodes[$id]['hops'] !== 5) {
	$nodes[$id]['hops'] = FALSE;

$inputArr = array_merge(array($id, $name, $hops));

$fp = fopen("zwave.txt", "a+");

fputcsv($fp, $inputArr);
1 Like

huh. how... wow. Didn't think you could actually clone a zwave network. cool.

I really need to look at OWZCP more. I really wanted to see a good topology, but it wasn't ever loading right.

Wish Hubitat would roll something internally... seems like it should be doable given the info (devices all report their visible neighbors).

I need to win the lottery is what this really comes down to. =)

A very recent post by @bravenel hinted at being able to backup the zwave and ZigBee databases in a future update.