00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 import os
00011 import string
00012 import subprocess
00013 import time
00014 import uuid
00015 import threading
00016
00017 import rocon_console.console as console
00018
00019 from . import utils
00020
00021
00022
00023
00024
00025
00026 def rocon_masters_cache_path():
00027 return os.path.join(utils.get_settings_cache_home(), "rocon_master.cache")
00028
00029
00030
00031
00032
00033
00034 class RoconMaster(object):
00035 __slots__ = [
00036 'index',
00037 'name',
00038 'uri',
00039 'host_name',
00040 'description',
00041 'icon',
00042 'flag',
00043 'current_row',
00044 ]
00045
00046 rocon_remocon_check_up_script = utils.find_rocon_remocon_script('rocon_remocon_check_up')
00047
00048 def __str__(self):
00049 s = self.name
00050 return s
00051
00052 def set_unknown(self):
00053 self.name = "Unknown"
00054 self.description = "Unknown."
00055 self.icon = "unknown.png"
00056 self.flag = '0'
00057
00058 def check(self):
00059 '''
00060 Given the uri and hostname, this proceeds to try and ping the rocon master to detect if it is available and
00061 if available, find the information on the other fields that fully describe a rocon master.
00062 '''
00063 if not (self.uri and self.host_name):
00064 console.logerror("Rocon Master : both uri and host_name should be configured before calling RoconMaster.check()")
00065 return
00066
00067 output = subprocess.Popen([RoconMaster.rocon_remocon_check_up_script, self.uri, self.host_name], stdout=subprocess.PIPE)
00068 time_out_cnt = 0
00069 while True:
00070 result = output.poll()
00071 if time_out_cnt > 30:
00072 console.logdebug("timeout: %s" % self.uri)
00073 try:
00074 output.terminate()
00075 except:
00076 console.logdebug("Error: output.terminate()")
00077 self.set_unknown()
00078 break
00079 elif result == 0:
00080 args = output.communicate()[0]
00081 self.name = args.split('\n')[0]
00082 self.description = args.split('\n')[1]
00083 self.icon = args.split('\n')[2]
00084
00085 if self.name == "Unknown":
00086 self.flag = '0'
00087 elif self.name == "Uncommunicable":
00088 self.flag = '1'
00089 else:
00090 self.flag = '2'
00091 break
00092
00093 time.sleep(0.1)
00094 time_out_cnt += 1
00095
00096
00097 class RoconMasters(object):
00098
00099 __slots__ = [
00100 'rocon_masters',
00101 ]
00102
00103 def __init__(self):
00104 self.rocon_masters = {}
00105 self.load()
00106
00107
00108
00109
00110
00111 def __contains__(self, index):
00112 return index in self.rocon_masters.keys()
00113
00114 def __getitem__(self, index):
00115 return self.rocon_masters[index]
00116
00117 def __len__(self):
00118 return len(self.rocon_masters)
00119
00120 def keys(self):
00121 return self.rocon_masters.keys()
00122
00123 def values(self):
00124 return self.rocon_masters.values()
00125
00126 def clear(self):
00127 self.rocon_masters.clear()
00128
00129
00130
00131
00132
00133 def __str__(self):
00134 s = console.cyan + 'Rocon Masters:' + console.reset
00135 for rocon_master in self.rocon_masters.values():
00136 s += '\n ' + console.yellow + str(rocon_master) + console.reset
00137 return s
00138
00139
00140
00141
00142
00143 def delete(self, index):
00144 del self.rocon_masters[index]
00145
00146 def add(self, uri, host_name):
00147 rocon_master = RoconMaster()
00148 rocon_master.index = str(uuid.uuid4())
00149 rocon_master.name = "Unknown"
00150 rocon_master.uri = uri
00151 rocon_master.host_name = host_name
00152 rocon_master.icon = "unknown.png"
00153 rocon_master.description = ""
00154 rocon_master.flag = "0"
00155 self.rocon_masters[rocon_master.index] = rocon_master
00156 return rocon_master
00157
00158
00159
00160
00161
00162 def load(self):
00163 """
00164 Gets a list of rocon masters and their info from cached data stored upon
00165 last exit of this application.
00166 """
00167
00168 self.rocon_masters = {}
00169 try:
00170 cache_rocon_master_info_list = open(rocon_masters_cache_path(), 'r')
00171 except:
00172 console.logdebug("Remocon : no cached settings found, moving on.")
00173 return
00174 lines = cache_rocon_master_info_list.readlines()
00175 for line in lines:
00176 if line.count("[index="):
00177 rocon_master = RoconMaster()
00178 rocon_master.index = line[string.find(line, "[index=") + len("[index="):string.find(line, ",name=")]
00179 rocon_master.name = line[string.find(line, "name=") + len("name="):string.find(line, ",master_uri=")]
00180 rocon_master.uri = line[string.find(line, ",master_uri=") + len(",master_uri="):string.find(line, ",host_name=")]
00181 rocon_master.host_name = line[string.find(line, ",host_name=") + len(",host_name="):string.find(line, ",description=")]
00182 rocon_master.description = line[string.find(line, ",description=") + len(",description="):string.find(line, ",icon=")]
00183 rocon_master.icon = line[string.find(line, ",icon=") + len(",icon="):string.find(line, ",flag=")]
00184 rocon_master.flag = line[string.find(line, ",flag=") + len(",flag="):string.find(line, "]")]
00185 self.rocon_masters[rocon_master.index] = rocon_master
00186 cache_rocon_master_info_list.close()
00187
00188 def dump(self):
00189 """
00190 Dump the rocon masters to a cache file.
00191 """
00192 try:
00193 cache_rocon_master_info_list = open(rocon_masters_cache_path(), 'w')
00194 except:
00195 console.logerror("Remocon : no directory or file: %s" % rocon_masters_cache_path())
00196 return
00197 for rocon_master in self.rocon_masters.values():
00198 rocon_master_elem = '['
00199 rocon_master_elem += 'index=' + str(rocon_master.index) + ','
00200 rocon_master_elem += 'name=' + str(rocon_master.name) + ','
00201 rocon_master_elem += 'master_uri=' + str(rocon_master.uri) + ','
00202 rocon_master_elem += 'host_name=' + str(rocon_master.host_name) + ','
00203 rocon_master_elem += 'description=' + str(rocon_master.description) + ','
00204 rocon_master_elem += 'icon=' + rocon_master.icon + ','
00205 rocon_master_elem += 'flag=' + rocon_master.flag
00206 rocon_master_elem += ']\n'
00207
00208 cache_rocon_master_info_list.write(rocon_master_elem)
00209 cache_rocon_master_info_list.close()
00210
00211 def check(self):
00212 """
00213 Ping and update information for all registered rocon masters.
00214 """
00215 thread_pool = []
00216 for rocon_master in self.rocon_masters.values():
00217 t = threading.Thread(target=rocon_master.check)
00218 t.start()
00219 thread_pool.append(t)
00220
00221 for t in thread_pool:
00222 t.join()