コード例 #1
0
    def reloadConfig(self, bootup=False):
        #load known sensors from file
        for k, v in self.config.items("childIds"):
            value = v.split(';')
            self.childIdLookupTable[value[0] + ";" + value[1]] = k
            self.availableIds[int(value[0])] = False

        #load unit M/I from file (A good programmer should check input values)
        self.unit = self.config.get('config', 'unit')

        #load InclutionMode from file and send it to gateway(A good programmer should check input values...)
        self.InclutionMode = self.config.get('config', 'inclusion-mode')

        #at bootup this is executed from init
        if bootup is False:
            self.setInclutionMode(self.InclutionMode)

        #initiate integrations
        #Openhab
        if self.config.get('config', 'openhab') == 'true':
            if self.oh is None:
                self.oh = Openhab(self.config, self.log)
            else:
                self.oh.reloadConfig()
        else:
            self.oh = None

        #Domoticz
        if self.config.get('config', 'domoticz') == 'true':
            if self.dom is None:
                self.dom = Domoticz(self.config, self.log)
            else:
                self.dom.reloadConfig()
        else:
            self.dom = None

        #RRD
        if self.config.get('config', 'rrd') == 'true':
            if self.rrd is None:
                self.rrd = Rrd(self.config, self.log)
            else:
                self.rrd.reloadConfig()
        else:
            self.rrd = None

        self.log.info("reloadConfig: Configuration reloaded.")
コード例 #2
0
ファイル: msgw.py プロジェクト: alannelson/ham
	def reloadConfig(self, bootup = False) :
		#load known sensors from file
		for k, v in self.config.items("childIds") :
			value = v.split(';')
			self.childIdLookupTable[value[0]+";"+value[1]] = k
			self.availableIds[int(value[0])]=False
		
		#load unit M/I from file (A good programmer should check input values)
		self.unit = self.config.get('config','unit')
		
		#load InclutionMode from file and send it to gateway(A good programmer should check input values...)
		self.InclutionMode = self.config.get('config','inclusion-mode')

		#at bootup this is executed from init
		if bootup is False :
			self.setInclutionMode(self.InclutionMode)
				
		
		#initiate integrations
		#Openhab
		if self.config.get('config','openhab') == 'true':
			if self.oh is None :
				self.oh = Openhab(self.config, self.log)
			else :
				self.oh.reloadConfig()
		else :
			self.oh = None
			
		#Domoticz
		if self.config.get('config','domoticz') == 'true':
			if self.dom is None :
				self.dom = Domoticz(self.config, self.log)
			else :
				self.dom.reloadConfig()
		else :
			self.dom = None
		
		#RRD
		if self.config.get('config','rrd') == 'true':
			if self.rrd is None :
				self.rrd = Rrd(self.config, self.log)
			else :
				self.rrd.reloadConfig()
		else :
			self.rrd = None
		
		self.log.info("reloadConfig: Configuration reloaded.")
コード例 #3
0
    def requestStatus(self, incomingData, childId, altId):
        self.log.debug("Requesting status for: " + altId)
        #A device request its current status from msgw (when staring up)
        index = int(incomingData[3])
        varType = self.tVarLookupNumType[index]

        #Requested variable value from one of the sensors
        variable = self.tVarTypes[varType]
        if (variable[2] is not None and childId is not None):
            value = None
            self.log.debug("Request status for " + variable[2])

            #openhab
            if self.config.has_option('openhab',
                                      childId) and self.oh is not None:
                oh = Openhab(self.config, self.log)
                value = self.oh.requestStatus(incomingData, childId, altId)
            #support others here like Domoticz

            #Get default if there is none in the external system
            if value is None:
                self.sendRequestResponse(altId, varType, variable[3])
            else:
                self.sendRequestResponse(altId, varType, value)
コード例 #4
0
ファイル: msgw.py プロジェクト: alannelson/ham
class msgw():
	
	#supported integrations
	oh = None
	dom = None
	rrd = None

	#supported version
	PLUGIN_VERSION = "1.2+"
	
	GATEWAY_VERSION = ""
	BAUD_RATE = "115200"
	ARDUINO_SID = "urn:upnp-arduino-cc:serviceId:arduino1"
	VARIABLE_CONTAINER_SID = "urn:upnp-org:serviceId:VContainer1"
	MAX_RADIO_ID=255
	NODE_CHILD_ID = "255"
	
	ARDUINO_DEVICE = None
	TASK_ERROR = 2
	TASK_ERROR_PERM = -2
	TASK_SUCCESS = 4
	TASK_BUSY = 1
	inclusionResult = {}
	includeCount = 0
	
	#Variables in msgw can be overridded in config file
	InclusionMode = 0
	unit = "M"
	
	#defines
	msgType = {
        'PRESENTATION' : "0",
        'SET_VARIABLE' : "1",
        'REQ_VARIABLE' : "2",
		'ACK_VARIABLE' : "3",
        'INTERNAL' : "4" }

	tDeviceLookupNumType = {}
	tDeviceTypes = {
        'DOOR' :                [0,  "urn:schemas-micasaverde-com:device:DoorSensor:1", "D_DoorSensor1.xml", "Door "],
        'MOTION' :      [1,  "urn:schemas-micasaverde-com:device:MotionSensor:1", "D_MotionSensor1.xml", "Motion "],
        'SMOKE' :       [2,  "urn:schemas-micasaverde-com:device:SmokeSensor:1", "D_SmokeSensor1.xml", "Smoke "],
        'LIGHT' :       [3,  "urn:schemas-upnp-org:device:BinaryLight:1", "D_BinaryLight1.xml", "Light "],
        'DIMMER' :      [4,  "urn:schemas-upnp-org:device:DimmableLight:1", "D_DimmableLight1.xml", "Dim Light "],
        'COVER' :       [5,  "urn:schemas-micasaverde-com:device:WindowCovering:1", "D_WindowCovering1.xml", "Window " ],
        'TEMP' :                [6,  "urn:schemas-micasaverde-com:device:TemperatureSensor:1", "D_TemperatureSensor1.xml", "Temp "],
        'HUM' :                 [7,  "urn:schemas-micasaverde-com:device:HumiditySensor:1", "D_HumiditySensor1.xml", "Humidity "],
        'BARO' :                [8,  "urn:schemas-micasaverde-com:device:BarometerSensor:1", "D_BarometerSensor1.xml", "Baro "],
        'WIND' :                [9,  "urn:schemas-micasaverde-com:device:WindSensor:1", "D_WindSensor1.xml", "Wind "],
        'RAIN' :                [10, "urn:schemas-micasaverde-com:device:RainSensor:1", "D_RainSensor1.xml", "Rain "],
        'UV' :          [11, "urn:schemas-micasaverde-com:device:UvSensor:1", "D_UvSensor1.xml", "UV "],
        'WEIGHT' :      [12, "urn:schemas-micasaverde-com:device:ScaleSensor:1", "D_ScaleSensor1.xml", "Weight "],
        'POWER' :       [13, "urn:schemas-micasaverde-com:device:PowerMeter:1", "D_PowerMeter1.xml", "Power "],
        'HEATER' :      [14, "urn:schemas-upnp-org:device:Heater:1", "D_Heater1.xml", "Heater "],
        'DISTANCE' :    [15, "urn:schemas-upnp-org:device:Distance:1", "D_DistanceSensor1.xml", "Distance "],
        'LIGHT_LEVEL':[16, "urn:schemas-micasaverde-com:device:LightSensor:1", "D_LightSensor1.xml", "Light "],
		'ARDUINO_NODE': [17, "urn:schemas-arduino-cc:device:arduinonode:1", "D_ArduinoNode1.xml", "Node "],
		'ARDUINO_RELAY':[18, "urn:schemas-arduino-cc:device:arduinorelay:1", "D_ArduinoRelay1.xml", "Relay "],
		'LOCK' : 		  [19, "urn:micasaverde-com:serviceId:DoorLock1", "D_DoorLock1.xml", "Lock "],
		'IR' : 		  [20, "urn:schemas-arduino-cc:device:ArduinoIr:1", "D_ArduinoIr1.xml", "IR "], 
		'WATER' : 	  [21, "urn:schemas-micasaverde-com:device:WaterMeter:1", "D_WaterMeter1.xml", "Water "]
	}

	tVarLookupNumType = {}
	tVarTypes = {
        'TEMP' : 			[0,  "urn:upnp-org:serviceId:TemperatureSensor1", "CurrentTemperature", ""],
	'HUM' : 			[1,  "urn:micasaverde-com:serviceId:HumiditySensor1", "CurrentLevel", "" ],
	'LIGHT' : 		[2,  "urn:upnp-org:serviceId:SwitchPower1", "Status", "0" ],
	'DIMMER' : 		[3,  "urn:upnp-org:serviceId:Dimming1", "LoadLevelStatus", "" ],
	'PRESSURE' : 		[4,  "urn:upnp-org:serviceId:BarometerSensor1", "CurrentPressure", "" ],
	'FORECAST' : 		[5,  "urn:upnp-org:serviceId:BarometerSensor1", "Forecast", "" ],
	'RAIN' : 			[6,  "urn:upnp-org:serviceId:RainSensor1", "CurrentTRain", "" ],
	'RAINRATE' : 		[7,  "urn:upnp-org:serviceId:RainSensor1", "CurrentRain", "" ],
	'WIND' : 			[8,  "urn:upnp-org:serviceId:WindSensor1", "AvgSpeed", "" ],
	'GUST' : 			[9,  "urn:upnp-org:serviceId:WindSensor1", "GustSpeed", "" ],
	'DIRECTION' : 	[10, "urn:upnp-org:serviceId:WindSensor1", "Direction", "" ],
	'UV' : 			[11, "urn:upnp-org:serviceId:UvSensor1", "CurrentLevel", "" ],
	'WEIGHT' : 		[12, "urn:micasaverde-com:serviceId:ScaleSensor1", "Weight", "" ],
	'DISTANCE' : 		[13, "urn:micasaverde-com:serviceId:DistanceSensor1", "CurrentDistance", "" ],
	'IMPEDANCE' : 	[14, "urn:micasaverde-com:serviceId:ScaleSensor1", "Impedance", "" ],
	'ARMED' : 		[15, "urn:micasaverde-com:serviceId:SecuritySensor1", "Armed", "" ],
	'TRIPPED' : 		[16, "urn:micasaverde-com:serviceId:SecuritySensor1", "Tripped", "0" ],
	'WATT' : 			[17, "urn:micasaverde-com:serviceId:EnergyMetering1", "Watts", "" ],
	'KWH' : 			[18, "urn:micasaverde-com:serviceId:EnergyMetering1", "KWH", "0" ],
	'SCENE_ON' : 		[19, "urn:micasaverde-com:serviceId:SceneController1", "sl_SceneActivated", "" ],
	'SCENE_OFF' : 	[20, "urn:micasaverde-com:serviceId:SceneController1", "sl_SceneDeactivated", "" ],
	'HEATER' : 		[21, "urn:upnp-org:serviceId:HVAC_UserOperatingMode1", "ModeStatus", "" ],
	'HEATER_SW' : 	[22, "urn:upnp-org:serviceId:SwitchPower1", "Status", "" ],
	'LIGHT_LEVEL' : 	[23, "urn:micasaverde-com:serviceId:LightSensor1", "CurrentLevel", "" ],
	'VAR_1' : 		[24, "urn:upnp-org:serviceId:VContainer1", "Variable1", ""],
	'VAR_2' : 		[25, "urn:upnp-org:serviceId:VContainer1", "Variable2", ""],
	'VAR_3' : 		[26, "urn:upnp-org:serviceId:VContainer1", "Variable3", ""],
	'VAR_4' : 		[27, "urn:upnp-org:serviceId:VContainer1", "Variable4", ""],
	'VAR_5' : 		[28, "urn:upnp-org:serviceId:VContainer1", "Variable5", ""],
	'UP' : 		    [29, None, None, ""],
	'DOWN' : 		    [30, None, None, ""],
	'STOP' : 			[31, None, None, ""],
	'IR_SEND' :		[32, None, None, ""],
	'IR_RECEIVE' : 	[33, "urn:upnp-org:serviceId:ArduinoIr1", "IrCode", ""],
	'FLOW' : 			[34, "urn:micasaverde-com:serviceId:WaterMetering1", "Flow", "" ],
	'VOLUME' : 		[35, "urn:micasaverde-com:serviceId:WaterMetering1", "Volume", "0" ],
	'LOCK' : 		    [36, "urn:micasaverde-com:serviceId:DoorLock1", "Status", ""]

	}

	tInternalLookupNumType = {}
	tInternalTypes = {
		"BATTERY_LEVEL" : [0, "urn:micasaverde-com:serviceId:HaDevice1", "BatteryLevel", "" ],
		"BATTERY_DATE" : 	[1, "urn:micasaverde-com:serviceId:HaDevice1", "BatteryDate", "" ],
		"LAST_TRIP" : 	[2, "urn:micasaverde-com:serviceId:SecuritySensor1", "LastTrip", "" ],
		"TIME" : 			[3, None, None, None],
		"VERSION" : 		[4, "urn:upnp-arduino-cc:serviceId:arduinonode1", "ArduinoLibVersion", ""],
		"REQUEST_ID" : 	[5, None, None, None],
		"INCLUSION_MODE" :[6, "urn:upnp-arduino-cc:serviceId:arduino1", "InclusionMode", "0"],
		"RELAY_NODE":     [7, "urn:upnp-arduino-cc:serviceId:arduinonode1", "RelayNode", ""],
		"LAST_UPDATE" : 	[8, "urn:micasaverde-com:serviceId:HaDevice1", "LastUpdate", "" ],
		"PING" : 			[9, None, None, None ],
		"PING_ACK" :      [10, None, None, None ],
		"LOG_MESSAGE" :   [11, None, None, None ],
		"CHILDREN" :  	[12, "urn:upnp-arduino-cc:serviceId:arduinonode1", "Children", "0"],
		"UNIT" :			[13, "urn:upnp-arduino-cc:serviceId:arduino1", "Unit", "M"],  # M : Metric / I : Imperial
		"SKETCH_NAME"    : [14, "urn:upnp-arduino-cc:serviceId:arduinonode1", "SketchName", ""],
	"SKETCH_VERSION" : [15, "urn:upnp-arduino-cc:serviceId:arduinonode1", "SketchVersion", ""]

	}	
	

	#lookup tables
	childIdLookupTable = {}
	availableIds = [True]*254
	
	for k, v in tVarTypes.iteritems():
		tVarLookupNumType[v[0]] = k

	for k, v in tDeviceTypes.iteritems():
		tDeviceLookupNumType[v[0]] = k
	
	for k, v in tInternalTypes.iteritems():
		tInternalLookupNumType[v[0]] = k
	
	
	#poor mans hook.
	def hooking(self,incomingData,ChildId) :
		index = int(incomingData[3]);
                variable = self.tVarTypes[self.tVarLookupNumType[index]]
                value = incomingData[4].strip()
		if int(ChildId) == 3 :
			f = open('/usr/share/nginx/www/info.dat', 'w')
			f.write(value)
			f.close()

	def loop(self):
		response = self.ser.readline()
		if response:
			self.log.debug("loop: Incomming message: "+response)
			self.processIncoming(response)
			return response
		return None

	def setVariable(self, incomingData, childId, nodeId):
		if (childId is not None) :
			# Set variable reported from a child sensor.
			childId = str(childId)
			index = int(incomingData[3]);
			varType = self.tVarLookupNumType[index]
			var = self.tVarTypes[varType]
			value = incomingData[4]
			if (var[1] is not None): 
				self.log.info("setVariable: RaidoId: "+incomingData[0]+" Sensor: "+incomingData[1]+" ChildId: "+str(childId)+" Type: " +self.tVarLookupNumType[index]+" reporting value: "+ value)
				
				#Support integrations			
				# Add info to RRD
				if self.config.has_option('rrds',childId) and self.rrd is not None:
					self.rrd.setVariable(incomingData, childId, nodeId)
				
				# Add info to Domoticz
				if self.config.has_option('domoticz',childId) and self.dom is not None:
					self.dom.setVariable(incomingData, childId, nodeId)
				
				# Add info to Openhab
				if self.config.has_option('openhab',childId) and self.oh is not None:
					self.oh.setVariable(incomingData, childId, nodeId)
				
				self.setVariableIfChanged(var[1], var[2], value, childId)
			
				# Handle special variables battery level and tripped which also
				# should update other variables to os.time(). This part should be removed...
				if (varType == "TRIPPED" and value == "1") :
					variable = self.tInternalTypes["LAST_TRIP"]
					self.setVariableIfChanged(variable[1], variable[2], int(time.time()), childId)

	# Still here since a lot of methods sends info to this one.
	def setVariableIfChanged(self, serviceId, name, value, deviceId):
	
		self.log.info("setVariableIfChanged: "+serviceId +","+name+", "+str(value)+", "+str(deviceId))
				
#done				
	def nextAvailiableRadioId(self):
		for i in xrange(10,254): 
			if (self.availableIds[i] == True):
				self.availableIds[i] = False
				return i
		return 255
				
#almost done
	def  presentation(self, incomingData, device, childId, altId):
		type = incomingData[3]
		data = incomingData[4]
		mode = bool(self.InclusionMode)

		if (mode == 'true' and device is None):
			#A new sensor (not created before) was presented during inclusion mode
			if (altId not in self.inclusionResult): 
				self.log.info("presentation: New sensor starting up. Radio: "+ incomingData[0] + " Sensor: "+incomingData[1])
				self.includeCount = self.includeCount+1;
				###check the line below need to do something
				#setVariableIfChanged(ARDUINO_SID, "InclusionFoundCountHR", includeCount .." devices found", ARDUINO_DEVICE)
				#calc and write to config file.
				
				#Find max current childId add one for the new sensor.
				# not nice but this is how I try to learn python, 5 years from now I will cry over this solution.
				index = -1
				for k, v in self.config.items("childIds") :
					if int(k) > index :
						index = int(k)
				
				index += 1
				
				self.childIdLookupTable[altId] = index
				self.config.set('childIds',str(index),altId+";"+type)
				
				self.writeConfigFile()
				
				self.inclusionResult[altId] = type
			elif (mode == 0 and device is not None and childId == self.NODE_CHILD_ID and data != self.GATEWAY_VERSION):
				#The library version of sensor differs from plugin version. Warn about it.
				self.log.warn("presentation: Doesn't match Gateway version("+self.GATEWAY_VERSION+ "). Radio: "+ incomingData[0] + " Sensor: "+incomingData[1] + " using version: " + incomingData[4])

#done is going to need a lot of work...					
	def processInternalMessage(self, incomingData, iChildId, iAltId):
		data = incomingData[4]
		index = int(incomingData[3]);
		varType = self.tInternalLookupNumType[index]
		var = self.tInternalTypes[varType]
	
		if (varType == "VERSION" and iAltId == "0;0"):
			#Store version of Arduino Gateway
			self.GATEWAY_VERSION = data
			self.log.info('processInternalMessage: Gateway running version: '+self.GATEWAY_VERSION )
			print("Connected to Mysensor Gateway running version %s" % data)
		elif ((varType == "SKETCH_NAME" or varType == "SKETCH_VERSION") and iChildId is not None) :
			# Store the Sketch name and Version
			v = self.config.get('childIds',str(iChildId))
			d = v.split(";")
			name = d[2]
			version = d[2]
			if varType == "SKETCH_NAME" : 
				name = data.rstrip()
			elif varType == "SKETCH_VERSION" :
				version = data.rstrip()
			
			self.config.set('childIds',str(iChildId),iAltId+";"+name+";"+version)
			
			self.writeConfigFile()

		elif (varType == "TIME"):
			#Request time was sent from one of the sensors
			self.sendInternalCommand(iAltId,"TIME",time.time())
		elif (varType == "UNIT"):
			#Request for unit was sent from one of the sensors
			self.sendInternalCommand(iAltId,"UNIT",self.unit)
		elif (varType == "REQUEST_ID"):
			#Determine next available radioid and sent it to the sensor
			self.sendInternalCommand(iAltId,"REQUEST_ID",self.nextAvailiableRadioId())
		elif (varType == "RELAY_NODE" and iChildId is not None):
			#Set human readable relay mode status
			self.setVariableIfChanged(var[1], var[2], data, iChildId)
			### Have a look at the one below
			#setVariableIfChanged(var[1], "RelayNodeHR", data == "0" and "GW" or data, iChildId)
		elif (varType == "BATTERY_LEVEL"):
		# Send to serVariable since you usally want to store this info.
			self.setVariable(incomingData, str(iChildId), iAltId)			
		elif (varType == "INCLUSION_MODE"):
			if data == "0" : 
				self.log.info("processInternalMessage: Inclusion mode started")
			elif data == "1" :
				self.log.info("processInternalMessage: Inclusion mode ended")
		elif (varType == "CHILDREN"):
			self.setVariableIfChanged(var[1], var[2], data, iChildId)
		elif (varType == "LOG_MESSAGE"):
			self.log.info("processInternalMessage: Log message:" + data)
		else:
			self.log.info("processInternalMessage: Incoming internal command discarded:" + data)
					
	def sendCommandOne(self,cmd):
		if self.ser.writable:
 			self.ser.write(cmd+"\n")
			self.log.debug("sendCommandOne: Sending: "+cmd)
		else:
			self.log.error("sendCommandOne: Can't write to serial port")

	def setUnit(unit): 
		self.setVariableIfChanged(ARDUINO_SID, "Unit", unit, ARDUINO_DEVICE)
		
			
#done			
	# Function to send a message to sensor
	def sendCommand(self, altid, variableId, value):
		return self.sendCommandWithMessageType(altid, "SET_VARIABLE", int(tVarTypes[variableId][0]), value)
#done	
	def sendNodeCommand(self, device, variableId, value):
		return self.sendCommandWithMessageType(device+";255", "SET_VARIABLE", int(tVarTypes[variableId][0]), value)
#done	
	def sendInternalCommand(self, altid, variableId, value):
		return self.sendCommandWithMessageType(altid, "INTERNAL", int(self.tInternalTypes[variableId][0]), str(value))
#done	
	def sendRequestResponse(self, altid, variableId, value):
		return self.sendCommandWithMessageType(altid, "ACK_VARIABLE", int(self.tVarTypes[variableId][0]), value)
		
#done	
	def sendCommandWithMessageType(self, altid, messageType, variableId, value):
		cmd = altid+";"+self.msgType[messageType]+";"+str(variableId)+";"+value+"\n"
		if self.ser.writable:
 			self.ser.write(cmd)
			self.log.debug("sendCommandWithMessageType: Sending: "+cmd)
			return True
		else:
			self.log.error("sendCommandWithMessageType: Can't write to serial port")
			return False

#done
	def processIncoming(self, s):
		self.log.info("processIncoming: Receiving: "+s)
		incomingData = s.split(';')
		if len(incomingData) >= 4:
			nodeId = incomingData[0]
			childId = incomingData[1]
			messageType = incomingData[2]
			altId = nodeId+";"+childId
			if altId in self.childIdLookupTable :
				device = self.childIdLookupTable[altId] 
			else :
				device = None

			if messageType==self.msgType["SET_VARIABLE"]:
				self.setVariable(incomingData, device, nodeId)
			elif messageType == self.msgType["PRESENTATION"]:
				self.presentation(incomingData, device, childId, altId)
			elif messageType == self.msgType["REQ_VARIABLE"]:
				self.requestStatus(incomingData, device, altId)
			elif messageType == self.msgType["INTERNAL"]:
				self.processInternalMessage(incomingData, device, altId)
			else:
				self.log.error("processIncoming: Error: Classic you shouldn't end up here: "+ s)
		else:
			self.log.error("processIncoming: Error: Receive unknown data: "+ s)

	def requestStatus(self, incomingData, childId, altId):
		self.log.debug("Requesting status for: "+altId)
		#A device request its current status from msgw (when staring up)
		index = int(incomingData[3])	
		varType = self.tVarLookupNumType[index]
		
		#Requested variable value from one of the sensors 
		variable = self.tVarTypes[varType]
		if (variable[2] is not None and childId is not None): 
			value = None
			self.log.debug("Request status for "+ variable[2])
			
			#openhab
			if self.config.has_option('openhab',childId) and self.oh is not None:
				oh = Openhab(self.config, self.log)
				value=self.oh.requestStatus(incomingData, childId, altId)
			#support others here like Domoticz
	

			#Get default if there is none in the external system
			if	value is None :
				self.sendRequestResponse(altId,varType,variable[3])
			else :
				self.sendRequestResponse(altId,varType,value)
			
	#Arduino GW device commands
	def startInclusion(self):
		self.config.set('config','inclusion-mode',"true")
		return self.sendInternalCommand("0;0","INCLUSION_MODE","1")


	def stopInclusion(self):
		self.config.set('config','inclusion-mode',"false")
		return self.sendInternalCommand("0;0","INCLUSION_MODE","0")

			
	#Arduino relay node device commands
	def fetchChildren(self, device):
		variable = self.tInternalTypes["CHILDREN"]
		self.setVariableIfChanged(variable[1], variable[2], "Fetching...", device)
		#self.sendInternalCommand(luup.devices[device].id,"CHILDREN","F")
		self.sendInternalCommand(luup.devices[device].id,"CHILDREN","F")

	def clearChildren(self, device):
		variable = self.tInternalTypes["CHILDREN"]
		self.setVariableIfChanged(variable[1], variable[2], "Clearing...", device)
		#self.sendInternalCommand(luup.devices[device].id,"CHILDREN","C")
		self.sendInternalCommand(device+";255","CHILDREN","C")

	def refreshRelay(self, device):
		variable = self.tInternalTypes["RELAY_NODE"]
		self.setVariableIfChanged(variable[1], variable[2], "Refreshing...", device)
		#self.sendInternalCommand(luup.devices[device].id,"RELAY_NODE","")
		self.sendInternalCommand(device+";255","RELAY_NODE","")

	def updateLookupTables(self, radioId, childId, deviceId):
		self.childIdLookupTable[radioId+";"+childId] = deviceId
		self.availableIds[radioId] = False

	### Support functions 	
	def reloadConfig(self, bootup = False) :
		#load known sensors from file
		for k, v in self.config.items("childIds") :
			value = v.split(';')
			self.childIdLookupTable[value[0]+";"+value[1]] = k
			self.availableIds[int(value[0])]=False
		
		#load unit M/I from file (A good programmer should check input values)
		self.unit = self.config.get('config','unit')
		
		#load InclutionMode from file and send it to gateway(A good programmer should check input values...)
		self.InclutionMode = self.config.get('config','inclusion-mode')

		#at bootup this is executed from init
		if bootup is False :
			self.setInclutionMode(self.InclutionMode)
				
		
		#initiate integrations
		#Openhab
		if self.config.get('config','openhab') == 'true':
			if self.oh is None :
				self.oh = Openhab(self.config, self.log)
			else :
				self.oh.reloadConfig()
		else :
			self.oh = None
			
		#Domoticz
		if self.config.get('config','domoticz') == 'true':
			if self.dom is None :
				self.dom = Domoticz(self.config, self.log)
			else :
				self.dom.reloadConfig()
		else :
			self.dom = None
		
		#RRD
		if self.config.get('config','rrd') == 'true':
			if self.rrd is None :
				self.rrd = Rrd(self.config, self.log)
			else :
				self.rrd.reloadConfig()
		else :
			self.rrd = None
		
		self.log.info("reloadConfig: Configuration reloaded.")
		
		
	#Parse Inclusion mode and sends the command to the Gateway
	def setInclutionMode(self, value) :
		if value == 'true' :
			self.startInclusion()
		elif value == 'false' :
			self.stopInclusion()
		else :
			self.log.warn("setInclutionMode : Invalid value :" +str(value))
		self.writeConfigFile()

	# Write persist the config file
	def writeConfigFile(self) :
		with open('msgw.conf', 'wb') as configfile:
			self.config.write(configfile)
	
	#Parse command from external GUI:s like Openhab move this to Openhab file
	def parseExternalCommand(self,external,name,type,state) :
		#Openhab support
		if external == "OpenHab" and self.oh is not None:
			value=self.oh.parseCommand(type,state)
			childId = self.oh.getChildIdFromNane(name)
			if type == "InclusionMode" :
				self.setInclutionMode(value)
			elif value is not None and childId is not None :
				device = self.config.get('childIds',childId)
				action=self.msgType["SET_VARIABLE"]
				self.sendCommandOne(device+";"+value+'\n')
			else :	
				self.log.error("parseExternalCommand: Missing value to send")
		#elif external == "Domoticz" ....
			#Write the code to support Domoticz
		else :
			self.log.error("parseExternalCommand: Don't support external commands for type: "+ external)
		
	#main
	def __init__(self, xconfig, xlog):
		self.log=xlog
		self.config=xconfig
	
		self.reloadConfig(True)
		
		#open serial interface 
		self.ser = serial.Serial(self.config.get('config','port'),self.config.get('config','baudrate'),timeout=1)
		self.log.info("Start up: Listening on :" + self.config.get('config','port') +" using baudrate: "+ self.config.get('config','baudrate') )
		self.ser.close()
		self.ser.open()
		
		print("Using Serial port %s at baudrate %s" % (self.config.get('config','port'), self.config.get('config','baudrate')))
		
		#Give Arduino time to start up.
		sleep(5)
		self.sendCommandWithMessageType("0;0","INTERNAL",int(self.tInternalTypes["VERSION"][0]),"Get Version")
		self.setInclutionMode(self.InclutionMode)
コード例 #5
0
class msgw():

    #supported integrations
    oh = None
    dom = None
    rrd = None

    #supported version
    PLUGIN_VERSION = "1.2+"

    GATEWAY_VERSION = ""
    BAUD_RATE = "115200"
    ARDUINO_SID = "urn:upnp-arduino-cc:serviceId:arduino1"
    VARIABLE_CONTAINER_SID = "urn:upnp-org:serviceId:VContainer1"
    MAX_RADIO_ID = 255
    NODE_CHILD_ID = "255"

    ARDUINO_DEVICE = None
    TASK_ERROR = 2
    TASK_ERROR_PERM = -2
    TASK_SUCCESS = 4
    TASK_BUSY = 1
    inclusionResult = {}
    includeCount = 0

    #Variables in msgw can be overridded in config file
    InclusionMode = 0
    unit = "M"

    #defines
    msgType = {
        'PRESENTATION': "0",
        'SET_VARIABLE': "1",
        'REQ_VARIABLE': "2",
        'ACK_VARIABLE': "3",
        'INTERNAL': "4"
    }

    tDeviceLookupNumType = {}
    tDeviceTypes = {
        'DOOR': [
            0, "urn:schemas-micasaverde-com:device:DoorSensor:1",
            "D_DoorSensor1.xml", "Door "
        ],
        'MOTION': [
            1, "urn:schemas-micasaverde-com:device:MotionSensor:1",
            "D_MotionSensor1.xml", "Motion "
        ],
        'SMOKE': [
            2, "urn:schemas-micasaverde-com:device:SmokeSensor:1",
            "D_SmokeSensor1.xml", "Smoke "
        ],
        'LIGHT': [
            3, "urn:schemas-upnp-org:device:BinaryLight:1",
            "D_BinaryLight1.xml", "Light "
        ],
        'DIMMER': [
            4, "urn:schemas-upnp-org:device:DimmableLight:1",
            "D_DimmableLight1.xml", "Dim Light "
        ],
        'COVER': [
            5, "urn:schemas-micasaverde-com:device:WindowCovering:1",
            "D_WindowCovering1.xml", "Window "
        ],
        'TEMP': [
            6, "urn:schemas-micasaverde-com:device:TemperatureSensor:1",
            "D_TemperatureSensor1.xml", "Temp "
        ],
        'HUM': [
            7, "urn:schemas-micasaverde-com:device:HumiditySensor:1",
            "D_HumiditySensor1.xml", "Humidity "
        ],
        'BARO': [
            8, "urn:schemas-micasaverde-com:device:BarometerSensor:1",
            "D_BarometerSensor1.xml", "Baro "
        ],
        'WIND': [
            9, "urn:schemas-micasaverde-com:device:WindSensor:1",
            "D_WindSensor1.xml", "Wind "
        ],
        'RAIN': [
            10, "urn:schemas-micasaverde-com:device:RainSensor:1",
            "D_RainSensor1.xml", "Rain "
        ],
        'UV': [
            11, "urn:schemas-micasaverde-com:device:UvSensor:1",
            "D_UvSensor1.xml", "UV "
        ],
        'WEIGHT': [
            12, "urn:schemas-micasaverde-com:device:ScaleSensor:1",
            "D_ScaleSensor1.xml", "Weight "
        ],
        'POWER': [
            13, "urn:schemas-micasaverde-com:device:PowerMeter:1",
            "D_PowerMeter1.xml", "Power "
        ],
        'HEATER': [
            14, "urn:schemas-upnp-org:device:Heater:1", "D_Heater1.xml",
            "Heater "
        ],
        'DISTANCE': [
            15, "urn:schemas-upnp-org:device:Distance:1",
            "D_DistanceSensor1.xml", "Distance "
        ],
        'LIGHT_LEVEL': [
            16, "urn:schemas-micasaverde-com:device:LightSensor:1",
            "D_LightSensor1.xml", "Light "
        ],
        'ARDUINO_NODE': [
            17, "urn:schemas-arduino-cc:device:arduinonode:1",
            "D_ArduinoNode1.xml", "Node "
        ],
        'ARDUINO_RELAY': [
            18, "urn:schemas-arduino-cc:device:arduinorelay:1",
            "D_ArduinoRelay1.xml", "Relay "
        ],
        'LOCK': [
            19, "urn:micasaverde-com:serviceId:DoorLock1", "D_DoorLock1.xml",
            "Lock "
        ],
        'IR': [
            20, "urn:schemas-arduino-cc:device:ArduinoIr:1",
            "D_ArduinoIr1.xml", "IR "
        ],
        'WATER': [
            21, "urn:schemas-micasaverde-com:device:WaterMeter:1",
            "D_WaterMeter1.xml", "Water "
        ]
    }

    tVarLookupNumType = {}
    tVarTypes = {
        'TEMP': [
            0, "urn:upnp-org:serviceId:TemperatureSensor1",
            "CurrentTemperature", ""
        ],
        'HUM': [
            1, "urn:micasaverde-com:serviceId:HumiditySensor1", "CurrentLevel",
            ""
        ],
        'LIGHT': [2, "urn:upnp-org:serviceId:SwitchPower1", "Status", "0"],
        'DIMMER':
        [3, "urn:upnp-org:serviceId:Dimming1", "LoadLevelStatus", ""],
        'PRESSURE':
        [4, "urn:upnp-org:serviceId:BarometerSensor1", "CurrentPressure", ""],
        'FORECAST':
        [5, "urn:upnp-org:serviceId:BarometerSensor1", "Forecast", ""],
        'RAIN': [6, "urn:upnp-org:serviceId:RainSensor1", "CurrentTRain", ""],
        'RAINRATE':
        [7, "urn:upnp-org:serviceId:RainSensor1", "CurrentRain", ""],
        'WIND': [8, "urn:upnp-org:serviceId:WindSensor1", "AvgSpeed", ""],
        'GUST': [9, "urn:upnp-org:serviceId:WindSensor1", "GustSpeed", ""],
        'DIRECTION':
        [10, "urn:upnp-org:serviceId:WindSensor1", "Direction", ""],
        'UV': [11, "urn:upnp-org:serviceId:UvSensor1", "CurrentLevel", ""],
        'WEIGHT':
        [12, "urn:micasaverde-com:serviceId:ScaleSensor1", "Weight", ""],
        'DISTANCE': [
            13, "urn:micasaverde-com:serviceId:DistanceSensor1",
            "CurrentDistance", ""
        ],
        'IMPEDANCE':
        [14, "urn:micasaverde-com:serviceId:ScaleSensor1", "Impedance", ""],
        'ARMED':
        [15, "urn:micasaverde-com:serviceId:SecuritySensor1", "Armed", ""],
        'TRIPPED':
        [16, "urn:micasaverde-com:serviceId:SecuritySensor1", "Tripped", "0"],
        'WATT':
        [17, "urn:micasaverde-com:serviceId:EnergyMetering1", "Watts", ""],
        'KWH':
        [18, "urn:micasaverde-com:serviceId:EnergyMetering1", "KWH", "0"],
        'SCENE_ON': [
            19, "urn:micasaverde-com:serviceId:SceneController1",
            "sl_SceneActivated", ""
        ],
        'SCENE_OFF': [
            20, "urn:micasaverde-com:serviceId:SceneController1",
            "sl_SceneDeactivated", ""
        ],
        'HEATER': [
            21, "urn:upnp-org:serviceId:HVAC_UserOperatingMode1", "ModeStatus",
            ""
        ],
        'HEATER_SW': [22, "urn:upnp-org:serviceId:SwitchPower1", "Status", ""],
        'LIGHT_LEVEL':
        [23, "urn:micasaverde-com:serviceId:LightSensor1", "CurrentLevel", ""],
        'VAR_1': [24, "urn:upnp-org:serviceId:VContainer1", "Variable1", ""],
        'VAR_2': [25, "urn:upnp-org:serviceId:VContainer1", "Variable2", ""],
        'VAR_3': [26, "urn:upnp-org:serviceId:VContainer1", "Variable3", ""],
        'VAR_4': [27, "urn:upnp-org:serviceId:VContainer1", "Variable4", ""],
        'VAR_5': [28, "urn:upnp-org:serviceId:VContainer1", "Variable5", ""],
        'UP': [29, None, None, ""],
        'DOWN': [30, None, None, ""],
        'STOP': [31, None, None, ""],
        'IR_SEND': [32, None, None, ""],
        'IR_RECEIVE': [33, "urn:upnp-org:serviceId:ArduinoIr1", "IrCode", ""],
        'FLOW': [
            34, "urn:micasaverde-com:serviceId:WaterMetering1", "Flow", ""
        ],
        'VOLUME': [
            35, "urn:micasaverde-com:serviceId:WaterMetering1", "Volume", "0"
        ],
        'LOCK': [36, "urn:micasaverde-com:serviceId:DoorLock1", "Status", ""]
    }

    tInternalLookupNumType = {}
    tInternalTypes = {
        "BATTERY_LEVEL":
        [0, "urn:micasaverde-com:serviceId:HaDevice1", "BatteryLevel", ""],
        "BATTERY_DATE":
        [1, "urn:micasaverde-com:serviceId:HaDevice1", "BatteryDate", ""],
        "LAST_TRIP":
        [2, "urn:micasaverde-com:serviceId:SecuritySensor1", "LastTrip", ""],
        "TIME": [3, None, None, None],
        "VERSION": [
            4, "urn:upnp-arduino-cc:serviceId:arduinonode1",
            "ArduinoLibVersion", ""
        ],
        "REQUEST_ID": [5, None, None, None],
        "INCLUSION_MODE":
        [6, "urn:upnp-arduino-cc:serviceId:arduino1", "InclusionMode", "0"],
        "RELAY_NODE":
        [7, "urn:upnp-arduino-cc:serviceId:arduinonode1", "RelayNode", ""],
        "LAST_UPDATE":
        [8, "urn:micasaverde-com:serviceId:HaDevice1", "LastUpdate", ""],
        "PING": [9, None, None, None],
        "PING_ACK": [10, None, None, None],
        "LOG_MESSAGE": [11, None, None, None],
        "CHILDREN":
        [12, "urn:upnp-arduino-cc:serviceId:arduinonode1", "Children", "0"],
        "UNIT": [13, "urn:upnp-arduino-cc:serviceId:arduino1", "Unit",
                 "M"],  # M : Metric / I : Imperial
        "SKETCH_NAME":
        [14, "urn:upnp-arduino-cc:serviceId:arduinonode1", "SketchName", ""],
        "SKETCH_VERSION": [
            15, "urn:upnp-arduino-cc:serviceId:arduinonode1", "SketchVersion",
            ""
        ]
    }

    #lookup tables
    childIdLookupTable = {}
    availableIds = [True] * 254

    for k, v in tVarTypes.iteritems():
        tVarLookupNumType[v[0]] = k

    for k, v in tDeviceTypes.iteritems():
        tDeviceLookupNumType[v[0]] = k

    for k, v in tInternalTypes.iteritems():
        tInternalLookupNumType[v[0]] = k

    #poor mans hook.
    def hooking(self, incomingData, ChildId):
        index = int(incomingData[3])
        variable = self.tVarTypes[self.tVarLookupNumType[index]]
        value = incomingData[4].strip()
        if int(ChildId) == 3:
            f = open('/usr/share/nginx/www/info.dat', 'w')
            f.write(value)
            f.close()

    def loop(self):
        response = self.ser.readline()
        if response:
            self.log.debug("loop: Incomming message: " + response)
            self.processIncoming(response)
            return response
        return None

    def setVariable(self, incomingData, childId, nodeId):
        if (childId is not None):
            # Set variable reported from a child sensor.
            childId = str(childId)
            index = int(incomingData[3])
            varType = self.tVarLookupNumType[index]
            var = self.tVarTypes[varType]
            value = incomingData[4]
            if (var[1] is not None):
                self.log.info("setVariable: RaidoId: " + incomingData[0] +
                              " Sensor: " + incomingData[1] + " ChildId: " +
                              str(childId) + " Type: " +
                              self.tVarLookupNumType[index] +
                              " reporting value: " + value)

                #Support integrations
                # Add info to RRD
                if self.config.has_option('rrds',
                                          childId) and self.rrd is not None:
                    self.rrd.setVariable(incomingData, childId, nodeId)

                # Add info to Domoticz
                if self.config.has_option('domoticz',
                                          childId) and self.dom is not None:
                    self.dom.setVariable(incomingData, childId, nodeId)

                # Add info to Openhab
                if self.config.has_option('openhab',
                                          childId) and self.oh is not None:
                    self.oh.setVariable(incomingData, childId, nodeId)

                self.setVariableIfChanged(var[1], var[2], value, childId)

                # Handle special variables battery level and tripped which also
                # should update other variables to os.time(). This part should be removed...
                if (varType == "TRIPPED" and value == "1"):
                    variable = self.tInternalTypes["LAST_TRIP"]
                    self.setVariableIfChanged(variable[1], variable[2],
                                              int(time.time()), childId)

    # Still here since a lot of methods sends info to this one.
    def setVariableIfChanged(self, serviceId, name, value, deviceId):

        self.log.info("setVariableIfChanged: " + serviceId + "," + name +
                      ", " + str(value) + ", " + str(deviceId))

#done

    def nextAvailiableRadioId(self):
        for i in xrange(10, 254):
            if (self.availableIds[i] == True):
                self.availableIds[i] = False
                return i
        return 255

#almost done

    def presentation(self, incomingData, device, childId, altId):
        type = incomingData[3]
        data = incomingData[4]
        mode = bool(self.InclusionMode)

        if (mode == 'true' and device is None):
            #A new sensor (not created before) was presented during inclusion mode
            if (altId not in self.inclusionResult):
                self.log.info("presentation: New sensor starting up. Radio: " +
                              incomingData[0] + " Sensor: " + incomingData[1])
                self.includeCount = self.includeCount + 1
                ###check the line below need to do something
                #setVariableIfChanged(ARDUINO_SID, "InclusionFoundCountHR", includeCount .." devices found", ARDUINO_DEVICE)
                #calc and write to config file.

                #Find max current childId add one for the new sensor.
                # not nice but this is how I try to learn python, 5 years from now I will cry over this solution.
                index = -1
                for k, v in self.config.items("childIds"):
                    if int(k) > index:
                        index = int(k)

                index += 1

                self.childIdLookupTable[altId] = index
                self.config.set('childIds', str(index), altId + ";" + type)

                self.writeConfigFile()

                self.inclusionResult[altId] = type
            elif (mode == 0 and device is not None
                  and childId == self.NODE_CHILD_ID
                  and data != self.GATEWAY_VERSION):
                #The library version of sensor differs from plugin version. Warn about it.
                self.log.warn("presentation: Doesn't match Gateway version(" +
                              self.GATEWAY_VERSION + "). Radio: " +
                              incomingData[0] + " Sensor: " + incomingData[1] +
                              " using version: " + incomingData[4])

#done is going to need a lot of work...

    def processInternalMessage(self, incomingData, iChildId, iAltId):
        data = incomingData[4]
        index = int(incomingData[3])
        varType = self.tInternalLookupNumType[index]
        var = self.tInternalTypes[varType]

        if (varType == "VERSION" and iAltId == "0;0"):
            #Store version of Arduino Gateway
            self.GATEWAY_VERSION = data
            self.log.info('processInternalMessage: Gateway running version: ' +
                          self.GATEWAY_VERSION)
            print("Connected to Mysensor Gateway running version %s" % data)
        elif ((varType == "SKETCH_NAME" or varType == "SKETCH_VERSION")
              and iChildId is not None):
            # Store the Sketch name and Version
            v = self.config.get('childIds', str(iChildId))
            d = v.split(";")
            name = d[2]
            version = d[2]
            if varType == "SKETCH_NAME":
                name = data.rstrip()
            elif varType == "SKETCH_VERSION":
                version = data.rstrip()

            self.config.set('childIds', str(iChildId),
                            iAltId + ";" + name + ";" + version)

            self.writeConfigFile()

        elif (varType == "TIME"):
            #Request time was sent from one of the sensors
            self.sendInternalCommand(iAltId, "TIME", time.time())
        elif (varType == "UNIT"):
            #Request for unit was sent from one of the sensors
            self.sendInternalCommand(iAltId, "UNIT", self.unit)
        elif (varType == "REQUEST_ID"):
            #Determine next available radioid and sent it to the sensor
            self.sendInternalCommand(iAltId, "REQUEST_ID",
                                     self.nextAvailiableRadioId())
        elif (varType == "RELAY_NODE" and iChildId is not None):
            #Set human readable relay mode status
            self.setVariableIfChanged(var[1], var[2], data, iChildId)
            ### Have a look at the one below
            #setVariableIfChanged(var[1], "RelayNodeHR", data == "0" and "GW" or data, iChildId)
        elif (varType == "BATTERY_LEVEL"):
            # Send to serVariable since you usally want to store this info.
            self.setVariable(incomingData, str(iChildId), iAltId)
        elif (varType == "INCLUSION_MODE"):
            if data == "0":
                self.log.info("processInternalMessage: Inclusion mode started")
            elif data == "1":
                self.log.info("processInternalMessage: Inclusion mode ended")
        elif (varType == "CHILDREN"):
            self.setVariableIfChanged(var[1], var[2], data, iChildId)
        elif (varType == "LOG_MESSAGE"):
            self.log.info("processInternalMessage: Log message:" + data)
        else:
            self.log.info(
                "processInternalMessage: Incoming internal command discarded:"
                + data)

    def sendCommandOne(self, cmd):
        if self.ser.writable:
            self.ser.write(cmd + "\n")
            self.log.debug("sendCommandOne: Sending: " + cmd)
        else:
            self.log.error("sendCommandOne: Can't write to serial port")

    def setUnit(unit):
        self.setVariableIfChanged(ARDUINO_SID, "Unit", unit, ARDUINO_DEVICE)

#done
# Function to send a message to sensor

    def sendCommand(self, altid, variableId, value):
        return self.sendCommandWithMessageType(altid, "SET_VARIABLE",
                                               int(tVarTypes[variableId][0]),
                                               value)
#done

    def sendNodeCommand(self, device, variableId, value):
        return self.sendCommandWithMessageType(device + ";255", "SET_VARIABLE",
                                               int(tVarTypes[variableId][0]),
                                               value)
#done

    def sendInternalCommand(self, altid, variableId, value):
        return self.sendCommandWithMessageType(
            altid, "INTERNAL", int(self.tInternalTypes[variableId][0]),
            str(value))
#done

    def sendRequestResponse(self, altid, variableId, value):
        return self.sendCommandWithMessageType(
            altid, "ACK_VARIABLE", int(self.tVarTypes[variableId][0]), value)

#done

    def sendCommandWithMessageType(self, altid, messageType, variableId,
                                   value):
        cmd = altid + ";" + self.msgType[messageType] + ";" + str(
            variableId) + ";" + value + "\n"
        if self.ser.writable:
            self.ser.write(cmd)
            self.log.debug("sendCommandWithMessageType: Sending: " + cmd)
            return True
        else:
            self.log.error(
                "sendCommandWithMessageType: Can't write to serial port")
            return False

#done

    def processIncoming(self, s):
        self.log.info("processIncoming: Receiving: " + s)
        incomingData = s.split(';')
        if len(incomingData) >= 4:
            nodeId = incomingData[0]
            childId = incomingData[1]
            messageType = incomingData[2]
            altId = nodeId + ";" + childId
            if altId in self.childIdLookupTable:
                device = self.childIdLookupTable[altId]
            else:
                device = None

            if messageType == self.msgType["SET_VARIABLE"]:
                self.setVariable(incomingData, device, nodeId)
            elif messageType == self.msgType["PRESENTATION"]:
                self.presentation(incomingData, device, childId, altId)
            elif messageType == self.msgType["REQ_VARIABLE"]:
                self.requestStatus(incomingData, device, altId)
            elif messageType == self.msgType["INTERNAL"]:
                self.processInternalMessage(incomingData, device, altId)
            else:
                self.log.error(
                    "processIncoming: Error: Classic you shouldn't end up here: "
                    + s)
        else:
            self.log.error("processIncoming: Error: Receive unknown data: " +
                           s)

    def requestStatus(self, incomingData, childId, altId):
        self.log.debug("Requesting status for: " + altId)
        #A device request its current status from msgw (when staring up)
        index = int(incomingData[3])
        varType = self.tVarLookupNumType[index]

        #Requested variable value from one of the sensors
        variable = self.tVarTypes[varType]
        if (variable[2] is not None and childId is not None):
            value = None
            self.log.debug("Request status for " + variable[2])

            #openhab
            if self.config.has_option('openhab',
                                      childId) and self.oh is not None:
                oh = Openhab(self.config, self.log)
                value = self.oh.requestStatus(incomingData, childId, altId)
            #support others here like Domoticz

            #Get default if there is none in the external system
            if value is None:
                self.sendRequestResponse(altId, varType, variable[3])
            else:
                self.sendRequestResponse(altId, varType, value)

    #Arduino GW device commands
    def startInclusion(self):
        self.config.set('config', 'inclusion-mode', "true")
        return self.sendInternalCommand("0;0", "INCLUSION_MODE", "1")

    def stopInclusion(self):
        self.config.set('config', 'inclusion-mode', "false")
        return self.sendInternalCommand("0;0", "INCLUSION_MODE", "0")

    #Arduino relay node device commands
    def fetchChildren(self, device):
        variable = self.tInternalTypes["CHILDREN"]
        self.setVariableIfChanged(variable[1], variable[2], "Fetching...",
                                  device)
        #self.sendInternalCommand(luup.devices[device].id,"CHILDREN","F")
        self.sendInternalCommand(luup.devices[device].id, "CHILDREN", "F")

    def clearChildren(self, device):
        variable = self.tInternalTypes["CHILDREN"]
        self.setVariableIfChanged(variable[1], variable[2], "Clearing...",
                                  device)
        #self.sendInternalCommand(luup.devices[device].id,"CHILDREN","C")
        self.sendInternalCommand(device + ";255", "CHILDREN", "C")

    def refreshRelay(self, device):
        variable = self.tInternalTypes["RELAY_NODE"]
        self.setVariableIfChanged(variable[1], variable[2], "Refreshing...",
                                  device)
        #self.sendInternalCommand(luup.devices[device].id,"RELAY_NODE","")
        self.sendInternalCommand(device + ";255", "RELAY_NODE", "")

    def updateLookupTables(self, radioId, childId, deviceId):
        self.childIdLookupTable[radioId + ";" + childId] = deviceId
        self.availableIds[radioId] = False

    ### Support functions
    def reloadConfig(self, bootup=False):
        #load known sensors from file
        for k, v in self.config.items("childIds"):
            value = v.split(';')
            self.childIdLookupTable[value[0] + ";" + value[1]] = k
            self.availableIds[int(value[0])] = False

        #load unit M/I from file (A good programmer should check input values)
        self.unit = self.config.get('config', 'unit')

        #load InclutionMode from file and send it to gateway(A good programmer should check input values...)
        self.InclutionMode = self.config.get('config', 'inclusion-mode')

        #at bootup this is executed from init
        if bootup is False:
            self.setInclutionMode(self.InclutionMode)

        #initiate integrations
        #Openhab
        if self.config.get('config', 'openhab') == 'true':
            if self.oh is None:
                self.oh = Openhab(self.config, self.log)
            else:
                self.oh.reloadConfig()
        else:
            self.oh = None

        #Domoticz
        if self.config.get('config', 'domoticz') == 'true':
            if self.dom is None:
                self.dom = Domoticz(self.config, self.log)
            else:
                self.dom.reloadConfig()
        else:
            self.dom = None

        #RRD
        if self.config.get('config', 'rrd') == 'true':
            if self.rrd is None:
                self.rrd = Rrd(self.config, self.log)
            else:
                self.rrd.reloadConfig()
        else:
            self.rrd = None

        self.log.info("reloadConfig: Configuration reloaded.")

    #Parse Inclusion mode and sends the command to the Gateway
    def setInclutionMode(self, value):
        if value == 'true':
            self.startInclusion()
        elif value == 'false':
            self.stopInclusion()
        else:
            self.log.warn("setInclutionMode : Invalid value :" + str(value))
        self.writeConfigFile()

    # Write persist the config file
    def writeConfigFile(self):
        with open('msgw.conf', 'wb') as configfile:
            self.config.write(configfile)

    #Parse command from external GUI:s like Openhab move this to Openhab file
    def parseExternalCommand(self, external, name, type, state):
        #Openhab support
        if external == "OpenHab" and self.oh is not None:
            value = self.oh.parseCommand(type, state)
            childId = self.oh.getChildIdFromNane(name)
            if type == "InclusionMode":
                self.setInclutionMode(value)
            elif value is not None and childId is not None:
                device = self.config.get('childIds', childId)
                action = self.msgType["SET_VARIABLE"]
                self.sendCommandOne(device + ";" + value + '\n')
            else:
                self.log.error("parseExternalCommand: Missing value to send")
        #elif external == "Domoticz" ....
        #Write the code to support Domoticz
        else:
            self.log.error(
                "parseExternalCommand: Don't support external commands for type: "
                + external)

    #main
    def __init__(self, xconfig, xlog):
        self.log = xlog
        self.config = xconfig

        self.reloadConfig(True)

        #open serial interface
        self.ser = serial.Serial(self.config.get('config', 'port'),
                                 self.config.get('config', 'baudrate'),
                                 timeout=1)
        self.log.info("Start up: Listening on :" +
                      self.config.get('config', 'port') + " using baudrate: " +
                      self.config.get('config', 'baudrate'))
        self.ser.close()
        self.ser.open()

        print("Using Serial port %s at baudrate %s" % (self.config.get(
            'config', 'port'), self.config.get('config', 'baudrate')))

        #Give Arduino time to start up.
        sleep(5)
        self.sendCommandWithMessageType("0;0", "INTERNAL",
                                        int(self.tInternalTypes["VERSION"][0]),
                                        "Get Version")
        self.setInclutionMode(self.InclutionMode)