kitcube.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import re
  2. from gluon import DAL, Field
  3. # from gluon.dal import Row, Rows
  4. dal_field_type = dict(
  5. id='id',
  6. bit='boolean',
  7. tinyint='boolean',
  8. int='integer',
  9. bigint='bigint',
  10. double='double',
  11. float='double',
  12. mediumblob='blob',
  13. blob='blob',
  14. varchar='string',
  15. text='text'
  16. )
  17. def search_objects(objs, **kargs):
  18. ''' search list of objects, matching supplied fields'''
  19. return filter(lambda s: all([ s[k] == v for k,v in kargs.iteritems() ]), objs)
  20. def search_objects2(axes, sensor_name, module_mark):
  21. for ax in axes:
  22. if (ax['sensor_name'] == sensor_name) and (ax['module_mark'] == module_mark):
  23. return ax['unit']
  24. return None
  25. class DBConnector(object):
  26. def __init__(self, key, host, database):
  27. self._modules = None
  28. self._views = None
  29. self._module_pattern = None
  30. self.axis_list = 'Axislist'
  31. self.sensor_list = 'Sensorlist'
  32. self.key = key
  33. self.host = host
  34. self.database = database
  35. self.uri = "%s/%s" % (self.host, self.database)
  36. self.dal = DAL( self.uri, migrate=False, pool_size=10, lazy_tables=True)
  37. def extract(self):
  38. self._modules = self.extract_modules()
  39. self._sensors = self.extract_sensors(self._modules)
  40. def connect(self):
  41. self.extract()
  42. for mod in self._modules:
  43. s = search_objects(self._sensors, module_name=mod['name'])
  44. f = [ Field(k['name'], type=k['type'], length=k['length'], rname=k['rname']) for k in s ]
  45. self.dal.define_table(mod['name'], *f)
  46. def reconnect(self):
  47. self.dal._adapter.reconnect()
  48. def query(self, module, fields=None, len=1):
  49. db = self.dal
  50. if module not in self._modules:
  51. rows = []
  52. if fields is None:
  53. rows = db(db[module].id>0).select(db[module].ALL, orderby='id DESC', limitby=(0,len))
  54. else:
  55. fields = [ db[module][f] for f in fields ]
  56. rows = db(db[module].id>0).select(db[module].usec, *fields, orderby='id DESC', limitby=(0,len))
  57. return {module: rows.as_list()[::-1]}
  58. def query_view(self, view, len=1):
  59. res = {}
  60. for mod, cols in view:
  61. res.update(self.query(mod, cols, len=len))
  62. return res
  63. @property
  64. def module_pattern(self):
  65. return self._module_pattern
  66. @module_pattern.setter
  67. def module_pattern(self, value):
  68. self._module_pattern = re.compile(value)
  69. @property
  70. def modules(self):
  71. return self._modules
  72. @modules.setter
  73. def modules(self, value):
  74. self._modules = value
  75. @property
  76. def sensors(self):
  77. return self._sensors
  78. @property
  79. def views(self):
  80. return self._views
  81. @views.setter
  82. def views(self, value):
  83. self._views = value
  84. class KITCube(DBConnector):
  85. def __init__(self, key, host, database, ignore_fields=[], field_type_fix={}):
  86. self.ignore_fields = ignore_fields
  87. self.field_type_fix = field_type_fix
  88. super(KITCube, self).__init__(key, host, database)
  89. def extract_modules(self):
  90. ''' extract modules
  91. extrace from database when self._modules is not defined,
  92. otherwise filter self._modules,
  93. Returns:
  94. [{'name': <name>, 'mark': <module number>}, ... ]
  95. '''
  96. tables = [ tname for tname, in self.dal.executesql('show tables') ]
  97. if self._modules is None:
  98. matches = [ (tname, self.module_pattern.match(tname)) for tname in tables ]
  99. modules = [ dict(name=tname, mark=int(m.group('mod_mark'))) for tname, m in matches if m ]
  100. else:
  101. modules = [ t for t in self._modules if t in tables ]
  102. return modules
  103. def extract_sensors(self, modules):
  104. ''' extract sensors from database
  105. Args:
  106. modules: list of moudles to be extracted
  107. Returns:
  108. [ {
  109. 'name': <sensor name>, # dots in name is coverted to underscore
  110. 'rname': <sensor rname>, # original name from db, if it contains dots
  111. 'type': <sensor type>,
  112. 'length': <length>,
  113. 'unit': <unit>,
  114. 'module_mark': 'module_mark'
  115. },
  116. ...
  117. ...
  118. ]
  119. '''
  120. fld_type_pattern = re.compile('(?P<fld_type>\w+)\((?P<fld_length>\d*)\)')
  121. sensor_units = self.extract_units()
  122. sensors = []
  123. for mod in modules:
  124. cols = self.dal.executesql('show columns from ' + mod['name'])
  125. for fld_name, fld_type, _, fld_key, _, _ in cols:
  126. if '.' in fld_name:
  127. rname = fld_name
  128. fld_name = fld_name.replace('.', '_')
  129. else:
  130. rname = None
  131. fld_name_long = mod['name'] + '.' + fld_name
  132. if fld_key == 'PRI':
  133. fld_type = 'id'
  134. if fld_name_long in self.field_type_fix.keys():
  135. fld_type = self.field_type_fix[fld_name_long]
  136. m = fld_type_pattern.match(fld_type)
  137. if m:
  138. fld_type = m.group('fld_type')
  139. fld_length = m.group('fld_length')
  140. else:
  141. fld_length = None
  142. if fld_name_long in self.ignore_fields:
  143. continue
  144. if fld_type in ['mediumblob', 'blob']:
  145. continue
  146. s = search_objects(sensor_units, module=mod['mark'], name=rname or fld_name)
  147. try:
  148. unit = s[0]['unit']
  149. except:
  150. unit = None
  151. if rname is not None:
  152. rname = '`' + rname + '`'
  153. sensors.append(dict(name=fld_name, rname=rname,
  154. type=fld_type, length=fld_length,
  155. unit=unit, module_name=mod['name']))
  156. return sensors
  157. def extract_units(self):
  158. self.dal.define_table(self.axis_list,
  159. Field('id'), Field('unit', 'string'))
  160. self.dal.define_table(self.sensor_list,
  161. Field('id'), Field('name', 'string'),
  162. Field('module', 'integer'),
  163. Field('axis', 'reference %s' % self.axis_list))
  164. sensortable = self.dal[self.sensor_list]
  165. axistable = self.dal[self.axis_list]
  166. records = self.dal(sensortable.axis==axistable.id).select()
  167. sensor_units = [ dict(name=r[self.sensor_list].name,
  168. module=r[self.sensor_list].module,
  169. unit=r[self.axis_list].unit) for r in records ]
  170. return sensor_units