Domoticz + RaZberry (via HTTP)

Discussions about RaZberry - Z-Wave board for Raspberry computer
Post Reply
sdh
Posts: 66
Joined: 25 Feb 2014 11:37

Domoticz + RaZberry (via HTTP)

Post by sdh »

I am not sure how many users are using this combination, but lot of devices are not fully working (Fibaro Motion Sensor, Fibaro Flood Sensors at least from my devices). I am not sure if this is a device issue, z-way api issue or domoticz issues. If you raise issue on domoticz forums, the simple answer is to switch to openzwave which I don't want to do (but I have seen that my devices work with openzwave).

So the question is, where is the issue. Is it because of the domoticz RaZberry code that is not maintained for quite some time and z-way-server has moved from 1.4 to 1.7 and now 2.0 versions in the mean time. Is there some expert who could analyse and if feasible update the domoticz RaZberry adapter code as domoticz team is not very keen in maintaining that code, there preference is openzwave. The code is located on source forge and github (https://github.com/domoticz/domoticz). The location is domoticz/hardware/Razberry.cpp and domoticz/hardware/Razberry.h.
pofs
Posts: 688
Joined: 25 Mar 2011 19:03

Re: Domoticz + RaZberry (via HTTP)

Post by pofs »

After a quick look at Domoticz code, I'd say they've never supported Alarm and have a mistype in AlarmSensor CC code ("sensorSate" instead of "sensorState").
You should be more specific on which functions of the devices above are not fully working.
sdh
Posts: 66
Joined: 25 Feb 2014 11:37

Re: Domoticz + RaZberry (via HTTP)

Post by sdh »

For example, Motion sensor in z-way-server has Motion, Temp, Lux and Tamper Alarm endpoints. In domoticz, not all the end points get listed for some reason. None of the motions sensors list the Lux and Tamper Alarm end points and also the motion and temp values are not getting refreshed. Same is true for flood sensor.
I am not sure how much extra work it is for you, but it would be great if someone from your team could support this activity (at least align it to major z-way api releases/changes). That way users of RaZberry in Domoticz could greatly benefit.
sdh
Posts: 66
Joined: 25 Feb 2014 11:37

Re: Domoticz + RaZberry (via HTTP)

Post by sdh »

I tried to debug the code a bit by putting some logs and see that Aeon Multi Sensors all the data is being read but none of the data is getting read for Fibaro Multi Sensor.

Aeon 4in1 Multi Sensor:

Code: Select all

2015-01-27 19:42:41 Razberry: Device nodeID:2 label:Multi Sensor Living Balcony
2015-01-27 19:42:41 Razberry: Battery Device nodeID:2 label:Multi Sensor Living Balcony Battery:70
2015-01-27 19:42:41 Razberry: COMMAND_CLASS_SENSOR_BINARY nodeID:2 label:Multi Sensor Living Balcony
2015-01-27 19:42:41 Razberry: COMMAND_CLASS_SENSOR_MULTILEVEL Temperature nodeID:2 label:Multi Sensor Living Balcony Temperature
2015-01-27 19:42:41 Razberry: COMMAND_CLASS_SENSOR_MULTILEVEL Luminiscence nodeID:2 label:Multi Sensor Living Balcony Luminiscence
2015-01-27 19:42:41 Razberry: COMMAND_CLASS_SENSOR_MULTILEVEL Humidity nodeID:2 label:Multi Sensor Living Balcony Humidity
Fibaro Motion Sensor:

Code: Select all

2015-01-27 19:42:42 Razberry: Device nodeID:29 label:Motion Sensor  Master Bedroom
2015-01-27 19:42:42 Razberry: Battery Device nodeID:29 label:Motion Sensor  Master Bedroom Battery:0
Modified function in razberry.cpp

Code: Select all

void CRazberry::parseDevices(const Json::Value &devroot)
{
	for (Json::Value::iterator itt=devroot.begin(); itt!=devroot.end(); ++itt)
	{
		const std::string devID=itt.key().asString();

		unsigned long nodeID=atol(devID.c_str());
		if ((nodeID==255)||(nodeID==m_controllerID))
			continue; //skip ourself

		const Json::Value node=(*itt);

		_tZWaveDevice _device;
		_device.nodeID=nodeID;
		// Device status and battery
		_device.basicType =		node["data"]["basicType"]["value"].asInt();
		_device.label =		    node["data"]["givenName"]["value"].asString();
		_device.genericType =	node["data"]["genericType"]["value"].asInt();
		_device.specificType =	node["data"]["specificType"]["value"].asInt();
		_device.isListening =	node["data"]["isListening"]["value"].asBool();
		_device.sensor250=		node["data"]["sensor250"]["value"].asBool();
		_device.sensor1000=		node["data"]["sensor1000"]["value"].asBool();
		_device.isFLiRS =		!_device.isListening && (_device.sensor250 || _device.sensor1000);
		_device.hasWakeup =		(node["instances"]["0"]["commandClasses"]["132"].empty()==false);
		_device.hasBattery =	(node["instances"]["0"]["commandClasses"]["128"].empty()==false);

	   _log.Log(LOG_NORM,"Razberry: Device nodeID:%d label:%s",_device.nodeID, _device.label.c_str());

      const Json::Value nodeInstances=node["instances"];
		// For all instances
		bool haveMultipleInstance=(nodeInstances.size()>1);
		for (Json::Value::iterator ittInstance=nodeInstances.begin(); ittInstance!=nodeInstances.end(); ++ittInstance)
		{
			_device.commandClassID=0;
			_device.scaleID=-1;

			const std::string sID=ittInstance.key().asString();
			_device.instanceID=atoi(sID.c_str());
			_device.indexID=0;
			if ((_device.instanceID==0)&&(haveMultipleInstance))
				continue;// We skip instance 0 if there are more, since it should be mapped to other instances or their superposition

			const Json::Value instance=(*ittInstance);

			if (_device.hasBattery)
			{
				_device.batValue=instance["commandClasses"]["128"]["data"]["last"]["value"].asInt();
                _log.Log(LOG_NORM,"Razberry: Battery Device nodeID:%d label:%s Battery:%u",_device.nodeID, _device.label.c_str(),_device.batValue);
			}

			// Switches
			// We choose SwitchMultilevel first, if not available, SwhichBinary is chosen
			if (instance["commandClasses"]["38"].empty()==false)
			{
				//COMMAND_CLASS_SWITCH_MULTILEVEL
				_device.commandClassID=38;
				_device.devType= ZDTYPE_SWITCH_DIMMER;
				_device.intvalue=instance["commandClasses"]["38"]["data"]["level"]["value"].asInt();
				InsertDevice(_device);
                _log.Log(LOG_NORM,"Razberry: COMMAND_CLASS_SWITCH_MULTILEVEL nodeID:%d label:%s",_device.nodeID, _device.label.c_str());

			}
			else if (instance["commandClasses"]["37"].empty()==false)
			{
				//COMMAND_CLASS_SWITCH_BINARY
				_device.commandClassID=37;
				_device.devType= ZDTYPE_SWITCH_NORMAL;
				_device.intvalue=instance["commandClasses"]["37"]["data"]["level"]["value"].asInt();
				InsertDevice(_device);
                _log.Log(LOG_NORM,"Razberry: COMMAND_CLASS_SWITCH_BINARY nodeID:%d label:%s",_device.nodeID, _device.label.c_str());
			}

			// Add Sensor Binary
			if (instance["commandClasses"]["48"].empty()==false)
			{
				//COMMAND_CLASS_SENSOR_BINARY
				_device.commandClassID=48; //(binary switch, for example motion detector(PIR)
				_device.devType= ZDTYPE_SWITCH_NORMAL;
				if (instance["commandClasses"]["48"]["data"]["level"].empty()==false)
				{
					_device.intvalue=instance["commandClasses"]["48"]["data"]["level"]["value"].asInt();
					InsertDevice(_device);
				}
				else
				{
					const Json::Value inVal=instance["commandClasses"]["48"]["data"];
					for (Json::Value::iterator itt2=inVal.begin(); itt2!=inVal.end(); ++itt2)
					{
						const std::string sKey=itt2.key().asString();
						if (!isInt(sKey))
							continue; //not a scale
						if ((*itt2)["level"].empty()==false)
						{
							_device.instanceID=atoi(sKey.c_str());
							_device.indexID=0;
							std::string vstring=(*itt2)["level"]["value"].asString();
							if (vstring=="true")
								_device.intvalue=255;
							else if (vstring=="false")
								_device.intvalue=0;
							else
								_device.intvalue=atoi(vstring.c_str());
							InsertDevice(_device);
						}
					}
				}
                _log.Log(LOG_NORM,"Razberry: COMMAND_CLASS_SENSOR_BINARY nodeID:%d label:%s",_device.nodeID, _device.label.c_str());
			}

			// Add Sensor Multilevel
			if (instance["commandClasses"]["49"].empty()==false)
			{
                std::string label = _device.label;
				//COMMAND_CLASS_SENSOR_MULTILEVEL
				_device.commandClassID=49;
				_device.scaleMultiply=1;
				const Json::Value inVal=instance["commandClasses"]["49"]["data"];
				for (Json::Value::iterator itt2=inVal.begin(); itt2!=inVal.end(); ++itt2)
				{
					const std::string sKey=itt2.key().asString();
					if (!isInt(sKey))
						continue; //not a scale
					_device.scaleID=atoi(sKey.c_str());
					std::string sensorTypeString = (*itt2)["sensorTypeString"]["value"].asString();
					if (sensorTypeString=="Power")
					{
						_device.floatValue=(*itt2)["val"]["value"].asFloat();
						if (_device.scaleID == 4)
						{
							_device.commandClassID=49;
							_device.devType = ZDTYPE_SENSOR_POWER;
                            _device.label = label + " " + sensorTypeString;
							InsertDevice(_device);
                            _log.Log(LOG_NORM,"Razberry: COMMAND_CLASS_SENSOR_MULTILEVEL Power nodeID:%d label:%s",_device.nodeID, _device.label.c_str());
						}
					}
					else if (sensorTypeString=="Temperature")
					{
						_device.floatValue=(*itt2)["val"]["value"].asFloat();
						_device.commandClassID=49;
						_device.devType = ZDTYPE_SENSOR_TEMPERATURE;
                        _device.label = label + " " + sensorTypeString;
						InsertDevice(_device);
                        _log.Log(LOG_NORM,"Razberry: COMMAND_CLASS_SENSOR_MULTILEVEL Temperature nodeID:%d label:%s",_device.nodeID, _device.label.c_str());
					}
					else if (sensorTypeString=="Humidity")
					{
						_device.intvalue=(*itt2)["val"]["value"].asInt();
						_device.commandClassID=49;
						_device.devType = ZDTYPE_SENSOR_HUMIDITY;
                        _device.label = label + " " + sensorTypeString;
						InsertDevice(_device);
                        _log.Log(LOG_NORM,"Razberry: COMMAND_CLASS_SENSOR_MULTILEVEL Humidity nodeID:%d label:%s",_device.nodeID, _device.label.c_str());
					}
					else if (sensorTypeString=="Luminiscence")
					{
						_device.floatValue=(*itt2)["val"]["value"].asFloat();
						_device.commandClassID=49;
						_device.devType = ZDTYPE_SENSOR_LIGHT;
                        _device.label = label + " " + sensorTypeString;
						InsertDevice(_device);
                        _log.Log(LOG_NORM,"Razberry: COMMAND_CLASS_SENSOR_MULTILEVEL Luminiscence nodeID:%d label:%s",_device.nodeID, _device.label.c_str());
					}
				}
				//InsertDevice(_device);
			}

			// Meters which are supposed to be sensors (measurable)
			if (instance["commandClasses"]["50"].empty()==false)
			{
                std::string label = _device.label;
				//COMMAND_CLASS_METER
				const Json::Value inVal=instance["commandClasses"]["50"]["data"];
				for (Json::Value::iterator itt2=inVal.begin(); itt2!=inVal.end(); ++itt2)
				{
					const std::string sKey=itt2.key().asString();
					if (!isInt(sKey))
						continue; //not a scale
					_device.scaleID=atoi(sKey.c_str());
					int sensorType=(*itt2)["sensorType"]["value"].asInt();
					_device.floatValue=(*itt2)["val"]["value"].asFloat();
					std::string scaleString = (*itt2)["scaleString"]["value"].asString();
					if ((_device.scaleID == 0 || _device.scaleID == 2 || _device.scaleID == 4 || _device.scaleID == 5 || _device.scaleID == 6) && (sensorType == 1))
					{
						_device.commandClassID=50;
						_device.scaleMultiply=1;
						if (scaleString=="kWh")
						{
							_device.scaleMultiply=1000;
							_device.devType = ZDTYPE_SENSOR_POWERENERGYMETER;
						}
						else if (scaleString=="W")
						{
							_device.devType = ZDTYPE_SENSOR_POWER;
						}
						else if (scaleString=="V")
						{
							_device.devType = ZDTYPE_SENSOR_VOLTAGE;
						}
						else if (scaleString=="A")
						{
							_device.devType = ZDTYPE_SENSOR_AMPERE;
						}
						else if (scaleString=="Power Factor")
						{
							_device.devType = ZDTYPE_SENSOR_PERCENTAGE;
						}
						else
						{
							_log.Log(LOG_ERROR,"Razberry: Device Scale not handled at the moment, please report (nodeID:%d, instanceID:%d, Scale:%s)",_device.nodeID,_device.instanceID,scaleString.c_str());
							continue;
						}
                        _device.label = label + " " + scaleString;
						InsertDevice(_device);
                        _log.Log(LOG_NORM,"Razberry: COMMAND_CLASS_METER %s nodeID:%d label:%s",scaleString.c_str(),_device.nodeID,_device.label.c_str());
					}
				}
			}

			// Meters (true meter values)
			if (instance["commandClasses"]["50"].empty()==false)
			{
                std::string label = _device.label;
				//COMMAND_CLASS_METER
				const Json::Value inVal=instance["commandClasses"]["50"]["data"];
				for (Json::Value::iterator itt2=inVal.begin(); itt2!=inVal.end(); ++itt2)
				{
					const std::string sKey=itt2.key().asString();
					if (!isInt(sKey))
						continue; //not a scale
					_device.scaleID=atoi(sKey.c_str());
					int sensorType=(*itt2)["sensorType"]["value"].asInt();
					_device.floatValue=(*itt2)["val"]["value"].asFloat();
					std::string scaleString = (*itt2)["scaleString"]["value"].asString();
					if ((_device.scaleID == 0 || _device.scaleID == 2 || _device.scaleID == 4 || _device.scaleID == 5 || _device.scaleID == 6) && (sensorType == 1))
						continue; // we don't want to have measurable here (W, V, A, PowerFactor)
					_device.commandClassID=50;
					_device.scaleMultiply=1;
					if (scaleString=="kWh")
					{
						_device.scaleMultiply=1000;
						_device.devType = ZDTYPE_SENSOR_POWERENERGYMETER;
					}
					else if (scaleString=="W")
					{
						_device.devType = ZDTYPE_SENSOR_POWER;
					}
					else if (scaleString=="V")
					{
						_device.devType = ZDTYPE_SENSOR_VOLTAGE;
					}
					else if (scaleString=="A")
					{
						_device.devType = ZDTYPE_SENSOR_AMPERE;
					}
					else if (scaleString=="Power Factor")
					{
						_device.devType = ZDTYPE_SENSOR_PERCENTAGE;
					}
					else
					{
						_log.Log(LOG_ERROR,"Razberry: Device Scale not handled at the moment, please report (nodeID:%d, instanceID:%d, Scale:%s)",_device.nodeID,_device.instanceID,scaleString.c_str());
						continue;
					}
                    _device.label = label + " " + scaleString;
					InsertDevice(_device);
                    _log.Log(LOG_NORM,"Razberry: COMMAND_CLASS_METER %s nodeID:%d label:%s",scaleString.c_str(),_device.nodeID,_device.label.c_str());
				}
			}
			if (instance["commandClasses"]["64"].empty()==false)
			{
				//COMMAND_CLASS_THERMOSTAT_MODE
				int iValue=instance["commandClasses"]["64"]["data"]["mode"]["value"].asInt();
				if (iValue==0)
					_device.intvalue=0;
				else
					_device.intvalue=255;
				_device.commandClassID=64;
				_device.devType = ZDTYPE_SWITCH_NORMAL;
				InsertDevice(_device);
			}

			if (instance["commandClasses"]["67"].empty()==false)
			{
				//COMMAND_CLASS_THERMOSTAT_SETPOINT
				const Json::Value inVal=instance["commandClasses"]["67"]["data"];
				for (Json::Value::iterator itt2=inVal.begin(); itt2!=inVal.end(); ++itt2)
				{
					const std::string sKey=itt2.key().asString();
					if (!isInt(sKey))
						continue; //not a scale
					_device.floatValue=(*itt2)["val"]["value"].asFloat();
					_device.commandClassID=67;
					_device.scaleMultiply=1;
					_device.devType = ZDTYPE_SENSOR_SETPOINT;
					InsertDevice(_device);
				}
			}
			else if (instance["commandClasses"]["156"].empty()==false)
			{
				//COMMAND_CLASS_SENSOR_ALARM
				const Json::Value inVal=instance["commandClasses"]["156"]["data"];
				for (Json::Value::iterator itt2=inVal.begin(); itt2!=inVal.end(); ++itt2)
				{
					const std::string sKey=itt2.key().asString();
					if (!isInt(sKey))
						continue; //not a scale
					_device.intvalue=(*itt2)["sensorState"]["value"].asInt();
					_device.commandClassID=156;
					_device.devType = ZDTYPE_SWITCH_NORMAL;
					InsertDevice(_device);
                    _log.Log(LOG_NORM,"Razberry: COMMAND_CLASS_SENSOR_ALARM nodeID:%d label:%s",_device.nodeID, _device.label.c_str());
				}
			}
			//COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE 70
		}
	}
}
sdh
Posts: 66
Joined: 25 Feb 2014 11:37

Re: Domoticz + RaZberry (via HTTP)

Post by sdh »

I see that Fibaro Motion, Smoke, Door/Window and Flood sensors report multiple instances and the required values are split across instances:

Code: Select all

2015-01-28 06:24:03 Razberry: Device nodeID:18 label:Smoke Sensor Kitchen
2015-01-28 06:24:03 Razberry: Multi Instance Device nodeID:18 label:Smoke Sensor Kitchen
2015-01-28 06:24:03 Razberry: COMMAND_CLASS_SENSOR_MULTILEVEL Temperature nodeID:18 instanceID:0 label:Smoke Sensor Kitchen Temperature
2015-01-28 06:24:03 Razberry: Device nodeID:19 label:Flood Sensor Kitchen
2015-01-28 06:24:03 Razberry: Multi Instance Device nodeID:19 label:Flood Sensor Kitchen
2015-01-28 06:24:03 Razberry: COMMAND_CLASS_SENSOR_BINARY nodeID:19 instanceID:1 label:Flood Sensor Kitchen
2015-01-28 06:24:03 Razberry: COMMAND_CLASS_SENSOR_ALARM nodeID:19 instanceID:1 label:Flood Sensor Kitchen
2015-01-28 06:24:03 Razberry: COMMAND_CLASS_SENSOR_ALARM nodeID:19 instanceID:1 label:Flood Sensor Kitchen
2015-01-28 06:24:03 Razberry: COMMAND_CLASS_SENSOR_BINARY nodeID:19 instanceID:1 label:Flood Sensor Kitchen
2015-01-28 06:24:03 Razberry: COMMAND_CLASS_SENSOR_MULTILEVEL Temperature nodeID:19 instanceID:2 label:Flood Sensor Kitchen Temperature
2015-01-28 06:40:46 Razberry: Device nodeID:23 label:Door Sensor Main Door
2015-01-28 06:40:46 Razberry: Multi Instance Device nodeID:23 label:Door Sensor Main Door
2015-01-28 06:40:46 Razberry: COMMAND_CLASS_SENSOR_BINARY nodeID:23 instanceID:1 label:Door Sensor Main Door
2015-01-28 06:40:46 Razberry: COMMAND_CLASS_SENSOR_ALARM nodeID:23 instanceID:1 label:Door Sensor Main Door
2015-01-28 06:40:46 Razberry: COMMAND_CLASS_SENSOR_BINARY nodeID:23 instanceID:1 label:Door Sensor Main Door
2015-01-28 06:40:46 Razberry: COMMAND_CLASS_SENSOR_MULTILEVEL Temperature nodeID:23 instanceID:2 label:Door Sensor Main Door Temperature
2015-01-28 06:24:04 Razberry: Device nodeID:29 label:Motion Sensor  Master Bedroom
2015-01-28 06:24:04 Razberry: Multi Instance Device nodeID:29 label:Motion Sensor  Master Bedroom
2015-01-28 06:24:04 Razberry: COMMAND_CLASS_SENSOR_BINARY nodeID:29 instanceID:1 label:Motion Sensor  Master Bedroom
2015-01-28 06:24:04 Razberry: COMMAND_CLASS_SENSOR_MULTILEVEL Temperature nodeID:29 instanceID:1 label:Motion Sensor  Master Bedroom Temperature
2015-01-28 06:24:04 Razberry: COMMAND_CLASS_SENSOR_MULTILEVEL Luminiscence nodeID:29 instanceID:1 label:Motion Sensor  Master Bedroom Luminiscence
2015-01-28 06:24:04 Razberry: COMMAND_CLASS_SENSOR_ALARM nodeID:29 instanceID:1 label:Motion Sensor  Master Bedroom Luminiscence
In domoticz code, instance 0 is skipped in case of multi instance device and hence most of the data which is actually in instance 0 gets skipped.

Code: Select all

      const Json::Value nodeInstances=node["instances"];
		// For all instances
		bool haveMultipleInstance=(nodeInstances.size()>1);
		for (Json::Value::iterator ittInstance=nodeInstances.begin(); ittInstance!=nodeInstances.end(); ++ittInstance)
		{
			_device.commandClassID=0;
			_device.scaleID=-1;

			const std::string sID=ittInstance.key().asString();
			_device.instanceID=atoi(sID.c_str());
			_device.indexID=0;
			if ((_device.instanceID==0)&&(haveMultipleInstance))
            {
				continue;// We skip instance 0 if there are more, since it should be mapped to other instances or their superposition
            }
Any idea how to address this.
sdh
Posts: 66
Joined: 25 Feb 2014 11:37

Re: Domoticz + RaZberry (via HTTP)

Post by sdh »

Are there any rule/guidelines for multi instance devices in z-wave standard that define what information is included in what instance. Can someone who has access to the z-wave standard please help clarify this.
Quax1507
Posts: 46
Joined: 31 Mar 2015 12:19

Re: Domoticz + RaZberry (via HTTP)

Post by Quax1507 »

I just tried to use Domoticz with RaZberry.
No luck with Fibaro multisensor.
Any news on this issue?
Post Reply