#! /bin/env python2
#
# Author: Mario Kicherer
#

from __future__ import print_function
from remi import start, App, Server, gui
import dbus, time
from threading import Thread

g_gui_objs = []
dbus_dlm_intf = None
dbus_nameservice_intf = None
dbus_master_intf = None
cand_intf = None
cand_props_intf = None

stu_state = {}
node_states = {}
service_states = {}
evnet_states = {}
cand_props = {}
general_info = ""
#general_timer = Timer(10, update_general_info)

def dbus2str(val):
	if isinstance(val, dbus.String):
		return val.encode('utf8')
	elif isinstance(val, dbus.Byte):
		return str(int(val))
	else:
		return str(val)

class WebCtlApp(App):
	def __init__(self, *args):
		super(WebCtlApp, self).__init__(*args)
	
	def add_DLM(self):
		# table
		
		self.dlm_tab = lambda: None
		
		self.dlm_tab.vbox = gui.VBox(width="100%")
		
		self.dlm_tab.table = gui.TableWidget(2, 2, use_title=False)
		self.dlm_tab.table.style["min-width"] = "90%"
		
		row = gui.TableRow()
		row.append("NodeId")
		row.append("Status")
		row.append("Substatus")
		#row.append("BL version")
		row.append("HW version")
		row.append("SW version")
		row.append("Last change")
		for c in row.children.values():
			c.style["background-color"] = "#ccccff"
		self.dlm_tab.table.append(row, "head")
		
		self.dlm_tab.vbox.append(self.dlm_tab.table)
		
		# status label
		
		self.dlm_tab.stu_conn_status = gui.Label("")
		self.dlm_tab.vbox.append(self.dlm_tab.stu_conn_status)
		
		# update button
		
		self.dlm_tab.btn = gui.Button("Update")
		self.dlm_tab.btn.onclick.connect(self.update_dlm_nodes)
		self.dlm_tab.vbox.append(self.dlm_tab.btn)
		
		self.tb.add_tab(self.dlm_tab.vbox, "STU", None)
	
	def start_fsync(self, widget):
		from subprocess import check_output
		
		check_output("sync")
	
	def conv_last_contact(self, last_contact):
		from datetime import datetime
		return datetime.utcfromtimestamp(int(last_contact)).strftime('%Y-%m-%d %H:%M:%S UTC')
	
	def update_dlm_tab(self):
		#self.table.empty()
		
		#print("updating table", self, id(node_states))
		
		if dbus_dlm_intf:
			self.dlm_tab.stu_conn_status.set_text("STU: available (build: "+stu_state["version"]+")")
			self.dlm_tab.table.style["color"] = "#000000"
		else:
			self.dlm_tab.stu_conn_status.set_text("STU: unavailable")
			self.dlm_tab.table.style["color"] = "#888888"
		
		for nid in sorted(node_states.keys()):
			node = node_states[nid]
			
			if nid in self.dlm_tab.table.children.keys():
				row = self.dlm_tab.table.children[nid]
				
				row.children["name"].set_text( node["name"]+" (0x%x)" % nid )
				row.children["state"].set_text( dbus2str(node["state"]) )
				if "substate" in node:
					row.children["substate"].set_text( dbus2str(node["substate"]) )
				else:
					row.children["substate"].set_text("")
				
				if dbus2str(node["state"]) != "unknown":
					#row.children["ver"].set_text(
						#"HW: "+dbus2str(node["hw_version"])+
						#" SW: "+dbus2str(node["sw_version"])+
						#" E: "+dbus2str(node["e_stand"])+
						#" A: "+dbus2str(node["a_stand"])
						#)
					#"HW rev: "+dbus2str(node["hw_revision"])+
						#" E: "+dbus2str(node["hw_e_number"])+
						#" A: "+dbus2str(node["hw_a_number"])+
						#" MAT: "+dbus2str(node["hw_material_number"])+
						#" EQU: "+dbus2str(node["hw_equipment_number"])+
						#" SW: "+dbus2str(node["sw_major"])+"."+dbus2str(node["sw_minor"])+"."+dbus2str(node["sw_revision"])+" "+dbus2str(node["sw_build"])
					
					s = ""
					hw_keys = ["hw_revision", "hw_e_number", "hw_a_number", "hw_material_number", "hw_equipment_number"]
					for k in hw_keys:
						val = dbus2str(node[k])
						i = k.replace("hw_", "").replace("_num", "")
						s += " "+i+" "+val
					row.children["app_ver_hw"].set_text(s)
					
					s = ""
					sw_keys = ["sw_major", "sw_minor", "sw_revision", "sw_build"]
					for k in sw_keys:
						val = dbus2str(node[k])
						s += "."+val
					row.children["app_ver_sw"].set_text(s[1:])
					
					row.children["last_contact"].set_text( self.conv_last_contact(node["last_contact"]) )
				else:
					#row.children["ver"].set_text( "" )
					row.children["app_ver_sw"].set_text( "" )
					row.children["app_ver_hw"].set_text( "" )
					row.children["last_contact"].set_text( "" )
			else:
				row = gui.TableRow()
				
				row.append(node["name"]+" (0x%x)"%nid, "name")
				row.append(dbus2str(node["state"]), "state")
				if "substate" in node:
					row.append(dbus2str(node["substate"]), "substate")
				else:
					row.append("", "substate")
				
				if dbus2str(node["state"]) != "unknown":
					#row.append(
						#"HW: "+dbus2str(node["hw_version"])+
						#" SW: "+dbus2str(node["sw_version"])+
						#" E: "+dbus2str(node["e_stand"])+
						#" A: "+dbus2str(node["a_stand"]),
						#"ver")
					
					s = ""
					hw_keys = ["hw_revision", "hw_e_number", "hw_a_number", "hw_material_number", "hw_equipment_number"]
					for k in hw_keys:
						val = dbus2str(node[k])
						i = k.replace("hw_", "").replace("_number", "")
						s += " "+i+" "+val
					row.append(s, "app_ver_hw")
					
					s = ""
					sw_keys = ["sw_major", "sw_minor", "sw_revision", "sw_build"]
					for k in sw_keys:
						val = dbus2str(node[k])
						s += "."+val
					row.append(s[1:], "app_ver_sw")
					
					row.append(self.conv_last_contact(node["last_contact"]), "last_contact")
				else:
					#row.append("", "ver")
					row.append("", "app_ver_sw")
					row.append("", "app_ver_hw")
					row.append("", "last_contact")
				
				row.children["name"].style["text-align"] = "left"
				
				self.dlm_tab.table.append(row, nid)
	
	
	
	
	
	def add_general_info(self):
		self.gen_tab = lambda: None
		
		self.gen_tab.vbox = gui.VBox(width="100%")
		
		
		self.gen_tab.btn = gui.Button("Flush disk cache")
		self.gen_tab.btn.onclick.connect(self.start_fsync)
		self.gen_tab.vbox.append(self.gen_tab.btn)
		
		
		#self.gen_tab.table = gui.TableWidget(1, 1, use_title=False)
		self.gen_tab.text = gui.TextInput(single_line=False)
		#self.gen_tab.text = gui.Label("")
		#self.gen_tab.text = gui.Listview("")
		#self.gen_tab.text.set_read_only(True)
		
		self.gen_tab.text.attributes["rows"] = "70"
		
		self.gen_tab.vbox.append(self.gen_tab.text)
		
		self.tb.add_tab(self.gen_tab.vbox, "General", None)
	
	#def update_general_tab(self):
		#self.gen_tab.table.empty()
		
	
	
	
	def update_services(self):
		columns = ["desc", "state", "substate", "autoload", "starttime", "stoptime", "id"]
		for nid in sorted(service_states.keys()):
			service = service_states[nid]
			
			if nid in self.service_tab.table.children.keys():
				row = self.service_tab.table.children[nid]
				
				#row.children["name"].set_text( service["name"]+" (0x%x)" % nid )
				#row.children["state"].set_text( str(service["state"]) )
				#if str(service["state"]) != "unknown":
					#row.children["ver"].set_text( "HW: "+str(service["hw_version"])+" SW: "+str(service["sw_version"]) )
					#row.children["last_contact"].set_text( self.conv_last_contact(service["last_contact"]) )
				#else:
					#row.children["ver"].set_text( "" )
					#row.children["last_contact"].set_text( "" )
				
				for k in columns:
					row.children[k].set_text(dbus2str(service[k]))
			else:
				row = gui.TableRow()
				
				#row.append(service["name"]+" (0x%x)"%nid, "name")
				#row.append(str(service["state"]), "state")
				#if str(service["state"]) != "unknown":
					#row.append("HW: "+str(service["hw_version"])+" SW: "+str(service["sw_version"]), "ver")
					#row.append(self.conv_last_contact(service["last_contact"]), "last_contact")
				#else:
					#row.append("", "ver")
					#row.append("", "last_contact")
				
				#row.children["name"].style["text-align"] = "left"
				
				#for k, v in service.items():
					#if k in ["job", "job_path", "job_type", "path"]:
						#continue
					#print(k, v, end=" | ")
				#print(service)
				for k in columns:
					if k in service:
						row.append(dbus2str(service[k]), k)
					else:
						row.append("", k)
				
				self.service_tab.table.append(row, nid)
			
			if dbus2str(service["state"]) == "failed":
				for c in row.children.values():
					c.style["background-color"] = "#ffcccc"
			elif dbus2str(service["state"]) == "active":
				for c in row.children.values():
					c.style["background-color"] = "#ccffcc"
			elif dbus2str(service["state"]) == "inactive":
				for c in row.children.values():
					c.style["background-color"] = "#cccccc"
			elif dbus2str(service["state"]) != "active":
				for c in row.children.values():
					c.style["background-color"] = "#ffffcc"
			
			if "autoload" in service and dbus2str(service["autoload"]) == "disabled":
				row.children["autoload"].style["background-color"] = "#ffffcc"
	
	def add_services(self):
		self.service_tab = lambda: None
		
		self.service_tab.vbox = gui.VBox(width="100%")
		
		self.service_tab.table = gui.TableWidget(1, 1, use_title=False)
		self.service_tab.table.style["min-width"] = "80%"
		
		columns = ["desc", "state", "substate", "autoload", "starttime", "stoptime", "id"]
		row = gui.TableRow()
		for k in columns:
			row.append(k)
		for c in row.children.values():
			c.style["background-color"] = "#ccccff"
		self.service_tab.table.append(row)
		
		self.service_tab.vbox.append(self.service_tab.table)
		
		self.tb.add_tab(self.service_tab.vbox, "Services", None)
	
	
	
	def add_EvNet(self):
		self.evnet_tab = lambda: None
		
		self.evnet_tab.vbox = gui.VBox(width="100%")
		
		self.evnet_tab.stat_table = gui.TableWidget(1, 1, use_title=False)
		self.evnet_tab.stat_table.style["min-width"] = "50%"
		
		row = gui.TableRow()
		row.append("id")
		row.append("value")
		self.evnet_tab.stat_table.append(row, "header")
		
		self.evnet_tab.vbox.append(self.evnet_tab.stat_table)
		
		
		
		self.evnet_tab.table = gui.TableWidget(1, 1, use_title=False)
		self.evnet_tab.table.style["min-width"] = "80%"
		
		columns = ["id", "name", "description", "user", "node_id", "node_name"]
		row = gui.TableRow()
		for k in columns:
			row.append(k)
		for c in row.children.values():
			c.style["background-color"] = "#ccccff"
		self.evnet_tab.table.append(row, "header")
		
		self.evnet_tab.vbox.append(self.evnet_tab.table)
		
		self.tb.add_tab(self.evnet_tab.vbox, "EventNet", None)
	
	def update_evnet(self):
		#cand_props["test_errors"] = 5
		#for k, v in cand_props.items():
		##for k, v in {"a_errors": "b"}.items():
			##print(k,v)
			#if k.endswith("_errors"):
				#if k in self.evnet_tab.table.children.keys():
					#row = self.evnet_tab.stat_table.children[k]
					
					#row.children["value"].set_text(dbus2str(v))
				#else:
					#row = gui.TableRow()
					
					#row.append(dbus2str(k), "id")
					#row.append(dbus2str(v), "value")
					
					#self.evnet_tab.stat_table.append(row, k)
		
		columns = ["id", "name", "description", "user", "node_id", "node_name"]
		for nid in sorted(evnet_states.keys()):
			subsystem = evnet_states[nid]
			
			if nid in self.evnet_tab.table.children.keys():
				row = self.evnet_tab.table.children[nid]
				
				for k in columns:
					#if k == "description":
						##s = unicode(subsystem[k], 'utf8')
						#s = subsystem[k].encode('utf8')
						#row.children[k].set_text(s)
					#else:
						#row.children[k].set_text(str(subsystem[k]))
					row.children[k].set_text(dbus2str(subsystem[k]))
			else:
				row = gui.TableRow()
				
				for k in columns:
					#if k == "description":
						##s = unicode(subsystem[k], 'utf8')
						#s = subsystem[k].encode('utf8')
						#row.append(s, k)
					#else:
						#row.append(str(subsystem[k]), k)
					
					row.append(dbus2str(subsystem[k]), k)
				
				self.evnet_tab.table.append(row, nid)
			
			if int(subsystem["status"]) == 1:
				for c in row.children.values():
					c.style["background-color"] = "#ffcccc"
			else:
				for c in row.children.values():
					del c.style["background-color"]
			#elif str(subsystem["state"]) == "active":
				#for c in row.children.values():
					#c.style["background-color"] = "#ccffcc"
			#elif str(subsystem["state"]) == "inactive":
				#for c in row.children.values():
					#c.style["background-color"] = "#cccccc"
			#elif str(subsystem["state"]) != "active":
				#for c in row.children.values():
					#c.style["background-color"] = "#ffffcc"
		
		for nid in self.evnet_tab.table.children.keys():
			if nid not in [0, "0", "header"] and nid not in evnet_states:
				self.evnet_tab.table.remove_child(self.evnet_tab.table.children[nid])
	
	
	def main(self):
		self.tb = gui.TabBox(width='100%')
		
		self.add_DLM()
		self.add_services()
		self.add_EvNet()
		self.add_general_info()
		
		if self not in g_gui_objs:
			g_gui_objs.append(self)
		
		self.update_dlm_tab()
		#self.update_general_tab()
		self.update_services()
		self.update_evnet()
		
		return self.tb
	
	
	
	
	def update_dlm_nodes(self, widget):
		query_dlm_nodeStates()
		
		self.update_dlm_tab()

def update_general_info():
	from subprocess import check_output
	from time import sleep
	
	while True:
		s = ""
		s += check_output(["uname", "-a"])+"\n"
		s += check_output("uptime")+"\n"
		
		s += check_output("dpkg -l | grep -i abk | tr -s ' ' | cut -d \" \" -f2,3", shell=True)+"\n"
		s += check_output("dpkg -l | grep -i \"cand\|cm-eventnet-linux\|libcortex\|stu\|caneventdict\|desi-webctl\" |  tr -s ' ' | cut -d \" \" -f2,3", shell=True)+"\n"

		s += check_output("ifconfig")+"\n"
		s += check_output(["df", "-h"])+"\n"
		
		#general_info = s
		#print("gen info", s)
		
		for g_gui_obj in g_gui_objs:
			g_gui_obj.gen_tab.text.set_text(s)
		
		sleep(10)
	
	#general_timer.start()

def timestamp2str(timestamp):
	return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp/1000000))

def service_state_changed(intf, props_dict, invalid_list, path=None):
	#print(intf, props_dict, invalid_list)
	#print(path, intf)
	if intf != "org.freedesktop.systemd1.Unit":
		return
	
	if "ActiveState" in props_dict:
		service_states[path]["state"] = props_dict["ActiveState"]
	
	info_dict =  {
		"ActiveState": "state",
		"SubState": "substate",
		#"StateChangeTimestamp": "",
		"ActiveEnterTimestamp": "starttime",
		"ActiveExitTimestamp": "stoptime",
		"UnitFileState": "autload",
		}
	
	for info in info_dict.keys():
		if info in props_dict:
			if info == "ActiveEnterTimestamp" or info == "ActiveExitTimestamp":
				service_states[path][info_dict[info]] = timestamp2str(props_dict[info])
			else:
				service_states[path][info_dict[info]] = props_dict[info]
	
	for g_gui_obj in g_gui_objs:
		g_gui_obj.update_services()
	

def query_dlm_nodeStates():
	global node_states
		
	if not dbus_dlm_intf:
		return
	
	#print("query states")
	
	cur_node_states = dbus_dlm_intf.getNodeStates()
	
	for node in cur_node_states:
		#print(int(node[0]), node_states.keys())
		
		if int(node[0]) not in node_states:
			node_states[int(node[0])] = {}
		
		node_dict = node_states[int(node[0])]
		
		for kv in node[1]:
			node_dict[kv[0]] = kv[1]
	
	if not g_gui_objs:
		return
	
	for g_gui_obj in g_gui_objs:
		g_gui_obj.update_dlm_tab()
	
def dbus_nodeStateEvent_cb(nodeId, node_dic):
	#nodeId = 0
	#node_dic = [ ("hw_version", "1"), ("sw_version", "1"), ("state", "lala"), ("name", "toast") ]
	
	if int(nodeId) not in node_states:
		node_states[int(nodeId)] = {}
	
	node_dict = node_states[int(nodeId)]
	
	for kv in node_dic:
		node_dict[kv[0]] = kv[1]
	
	if not g_gui_objs:
		return
	
	for g_gui_obj in g_gui_objs:
		g_gui_obj.update_dlm_tab()

def update_cand_stats():
	from time import sleep
	
	while True:
		if cand_props_intf is None:
			sleep(1)
			continue
		
		try:
			cand_props = cand_props_intf.GetAll("org.desireos.cand")
		except dbus.DBusException:
			sleep(1)
			continue
		
		#print(cand_props)
		#cand_props["test_errors"] = 5
		
		#for intf, valdict in cand_props.items():
		for k in sorted(cand_props.keys()):
			v = cand_props[k]
		#for k, v in {"a_errors": "b"}.items():
			#print(k,v)
			#for k, v in valdict.items():
			#if k.endswith("_errors"):
			if True:
				for g_gui_obj in g_gui_objs:
					if k in g_gui_obj.evnet_tab.table.children.keys():
						row = g_gui_obj.evnet_tab.stat_table.children[k]
						
						row.children["value"].set_text(dbus2str(v))
					else:
						row = gui.TableRow()
						
						row.append(dbus2str(k), "id")
						row.append(dbus2str(v), "value")
						
						g_gui_obj.evnet_tab.stat_table.append(row, k)
		
		#for g_gui_obj in g_gui_objs:
			#g_gui_obj.gen_tab.text.set_text(s)
		
		sleep(10)

def evnet_query_state():
	#cand_props = cand_intf.GetAllProperties()
	
	#import logging
	#log = logging.getLogger('remi.gui')
	#log.info(cand_props)
	
	
	subsystem_list = dbus_nameservice_intf.getSubsystems()
	
	#for k, v in subsystem_list:
		#evnet_states[k] = v
	
	for subsystem in subsystem_list:
		if int(subsystem[0]) not in evnet_states:
			evnet_states[int(subsystem[0])] = {"id": int(subsystem[0])}
		
		subsystem_dict = evnet_states[int(subsystem[0])]
		
		for kv in subsystem[1]:
			subsystem_dict[kv[0]] = kv[1]
		
		if subsystem_dict["dbus_peer"]:
			try:
				uid = dbus_master_intf.GetConnectionUnixUser(subsystem_dict["dbus_peer"])
			except dbus.DBusException:
				subsystem_dict["user"] = ""
			else:
				import pwd
				subsystem_dict["user"] = pwd.getpwuid( uid ).pw_name
		else:
			subsystem_dict["user"] = ""
	
	for g_gui_obj in g_gui_objs:
		g_gui_obj.update_evnet()

def subsystem_state_changed(*args):
	subsystem = args
	
	if len(subsystem[1]) == 0:
		del evnet_states[int(subsystem[0])]
		
		for g_gui_obj in g_gui_objs:
			g_gui_obj.update_evnet()
		
		return
	
	if int(subsystem[0]) not in evnet_states:
		evnet_states[int(subsystem[0])] = {"id": int(subsystem[0])}
	
	subsystem_dict = evnet_states[int(subsystem[0])]
	
	for kv in subsystem[1]:
		subsystem_dict[kv[0]] = kv[1]
	
	if subsystem_dict["dbus_peer"]:
		try:
			uid = dbus_master_intf.GetConnectionUnixUser(subsystem_dict["dbus_peer"])
		except dbus.DBusException:
			subsystem_dict["user"] = ""
		else:
			import pwd
			subsystem_dict["user"] = pwd.getpwuid( uid ).pw_name
	else:
		subsystem_dict["user"] = ""
	
	for g_gui_obj in g_gui_objs:
		g_gui_obj.update_evnet()


def stu_available_cb(available):
	global dbus_dlm_intf
	global dbus_nameservice_intf
	global dbus_master_intf
	global cand_intf
	global cand_props_intf
	
	if available:
		try:
			dbus_dlm  = bus.get_object("org.desireos.stu", "/org/desireos/stu")
			
			dbus_dlm_intf = dbus.Interface(dbus_dlm, dbus_interface='org.desireos.stu')
			
			#dbus_dlm.connect_to_signal("dbus_nodeStateEvent_cb", dbus_nodeStateEvent_cb, dbus_interface="org.desireos.stu")
			#dbus_dlm_intf.connect_to_signal("dbus_nodeStateEvent_cb", dbus_nodeStateEvent_cb)
			
			print("DLM found")
			
			#bus.add_signal_receiver(dbus_nodeStateEvent_cb)
			bus.add_signal_receiver(dbus_nodeStateEvent_cb, dbus_interface="org.desireos.stu")
			
			state = dbus_dlm_intf.getState()
	
			for k, v in state:
				stu_state[k] = v
			
			query_dlm_nodeStates()
			
			
			
			dbus_services  = bus.get_object("org.freedesktop.systemd1", "/org/freedesktop/systemd1")
			
			dbus_services_intf = dbus.Interface(dbus_services, dbus_interface='org.freedesktop.systemd1.Manager')
			
			unit_list = dbus_services_intf.ListUnits()
			for unit in unit_list:
				if (dbus2str(unit[0]).find("abk") == -1 and
					dbus2str(unit[0]) not in [
						"stu.service", "cand.service", "dlmd.service",
						"cand-ctrl.service"
						]
					):
					continue
				
				service_states[unit[6]] = {}
				service_state = service_states[unit[6]]
				
				service_state["id"] = unit[0]
				service_state["desc"] = unit[1]
				service_state["loaded"] = unit[2]
				service_state["state"] = unit[3]
				service_state["substate"] = unit[4]
				service_state["other_unit"] = unit[5]
				service_state["path"] = unit[6]
				service_state["job"] = unit[7]
				service_state["job_type"] = unit[8]
				service_state["job_path"] = unit[9]
				
				service_state["obj"] = bus.get_object("org.freedesktop.systemd1", service_state["path"])
				
				#service_state["intf"] = dbus.Interface(service_state["obj"], dbus_interface='org.freedesktop.systemd1.Unit')
				service_state["props"] = dbus.Interface(service_state["obj"], dbus_interface='org.freedesktop.DBus.Properties')
				
				#print(service_state["props"].GetAll())
				service_state["autoload"] = service_state["props"].Get("org.freedesktop.systemd1.Unit", "UnitFileState")
				starttime = service_state["props"].Get("org.freedesktop.systemd1.Unit", "ActiveEnterTimestamp")
				stoptime = service_state["props"].Get("org.freedesktop.systemd1.Unit", "ActiveExitTimestamp")
				
				#print("service", unit[0])
				service_state["props"].connect_to_signal("PropertiesChanged", service_state_changed, path_keyword='path')
				#bus.add_signal_receiver(service_state_changed, dbus_interface='org.freedesktop.DBus.Properties', arg0=service_state, member_keyword = "PropertiesChanged")
				
				#service_state["starttime"] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(starttime/1000000))
				#service_state["stoptime"] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(stoptime/1000000))
				#print(service_state)
				service_state["starttime"] = timestamp2str(starttime)
				service_state["stoptime"] = timestamp2str(stoptime)
			
			
			
			
	
			dbus_master = bus.get_object("org.freedesktop.DBus", "/")
			dbus_master_intf = dbus.Interface(dbus_master, dbus_interface='org.freedesktop.DBus')
			
			dbus_nameservice  = bus.get_object("org.desireos.cand", "/org/desireos/cand/ns")
			
			dbus_nameservice_intf = dbus.Interface(dbus_nameservice, dbus_interface='org.desireos.cand.ns')
			
			dbus_nameservice_intf.connect_to_signal("SubsystemEvent", subsystem_state_changed)
			
			cand_obj = bus.get_object("org.desireos.cand", "/org/desireos/cand")
			cand_intf = dbus.Interface(cand_obj, dbus_interface='org.desireos.cand')
			cand_props_intf = dbus.Interface(cand_obj, dbus_interface='org.freedesktop.DBus.Properties')
			
			evnet_query_state()
			
			
		except dbus.DBusException as e:
			available = False
			print("error:", e)
	
	if not available:
		print("cannot reach STU")
		dbus_dlm_intf = None
		
		if not g_gui_objs:
			return
		
		for g_gui_obj in g_gui_objs:
			g_gui_obj.update_dlm_tab()

#def get_ip():
	#import socket
	#import fcntl
	#import struct

	#for intf in socket.if_nameindex():
		#s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
		#return socket.inet_ntoa(fcntl.ioctl(
			#s.fileno(),
			#0x8915,  # SIOCGIFADDR
			#struct.pack('256s', intf[:15])
		#)[20:24])

if __name__ == '__main__':
	import dbus.mainloop.glib
	from glib import MainLoop, threads_init
	from gobject import GObject
	import logging
	from socket import gethostname
	

	threads_init()
	
	loop = MainLoop()
	
	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
	dbus.mainloop.glib.threads_init()

	bus = dbus.SystemBus()
	
	bus.watch_name_owner("org.desireos.stu", stu_available_cb)
	
	
	debug = False
	#debug = True
	logging.basicConfig(level=logging.DEBUG if debug else logging.INFO,
					format='%(name)-16s %(levelname)-8s %(message)s')
	logging.getLogger('remi').setLevel(
			level=logging.DEBUG if debug else logging.INFO)
	
	
	title = "DesireOS status (%s)" % (gethostname())
	
	
	general_timer = Thread(target=update_general_info).start()
	#general_timer = Timer(10, update_general_info)
	#update_general_info()
	
	cand_stats_timer = Thread(target=update_cand_stats).start()
	
	s = Server(WebCtlApp, start=False, address="0.0.0.0", port=8080, multiple_instance=True, start_browser=False, title=title)
	
	s.start()
	
	try:
		loop.run()
	except KeyboardInterrupt:
		loop.quit()
	
	s.stop()
