rabin 7 years ago
commit
18d928fe3f
19 changed files with 1348 additions and 0 deletions
  1. 6 0
      __init__.py
  2. 233 0
      core.py
  3. 6 0
      db/__init__.py
  4. 26 0
      db/influxdb.py
  5. 26 0
      db/postgresql.py
  6. 6 0
      model/__init__.py
  7. 239 0
      model/base.py
  8. 382 0
      model/sql.py
  9. 6 0
      mqtt/__init__.py
  10. 49 0
      mqtt/connect.py
  11. 19 0
      mqtt/pub.py
  12. 20 0
      mqtt/sub.py
  13. 6 0
      tcp/__init__.py
  14. 24 0
      tcp/client.py
  15. 49 0
      tcp/server.py
  16. 6 0
      web/__init__.py
  17. 35 0
      web/api.py
  18. 49 0
      web/application.py
  19. 161 0
      web/base.py

+ 6 - 0
__init__.py

@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter init
+    author:rabin
+"""

+ 233 - 0
core.py

@@ -0,0 +1,233 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter core
+    name:demeter.py
+    author:rabin
+"""
+import time
+import os
+import sys
+import getopt
+import ConfigParser
+import subprocess
+PATH = ''
+class Demeter(object):
+	path = ''
+	config = {}
+	serviceObj = {}
+	modelObj = {}
+	web = ''
+
+	def __new__(cls, *args, **kwargs):
+		print 'error'
+		sys.exit()
+
+	def __init__(self):
+		pass
+
+	@classmethod
+	def initConfig(cls):
+		global PATH
+		if PATH == '':
+			PATH = File.path()
+		cls.path = PATH
+		if cls.config == {}:
+			name = 'dev'
+			if 'DEMETER_CONF' in os.environ:
+				name = os.environ['DEMETER_CONF']
+			filename = cls.path + 'conf/'+name+'.conf'
+			if File.exists(filename):
+				config = ConfigParser.ConfigParser()
+				config.read(filename)
+
+				for item in config.sections():
+					cls.config[item] = cls.readConfig(config, item)
+				return True
+			else:
+				print filename + ' is not exists'
+				sys.exit()
+
+	@staticmethod
+	def readConfig(config, type):
+		value = config.options(type)
+		result = {}
+		for item in value:
+			result[item] = config.get(type, item)
+		return result
+
+	@classmethod
+	def echo(cls, args):
+		module = cls.getObject('pprint')
+		module.pprint(args)
+
+	@classmethod
+	def record(cls, key, value):
+		# 记录日志
+		# cls.log(key, value)
+		service = cls.service('record')
+		service.push(key, value)
+
+	@classmethod
+	def service(cls, name):
+		if name not in cls.serviceObj:
+			service = cls.getClass(name, 'service.')
+			cls.serviceObj[name] = service()
+		return cls.serviceObj[name]
+
+	@classmethod
+	def model(cls, table, type='rdb'):
+		if table not in cls.modelObj:
+			type = cls.config['db'][type]
+			config = cls.config[type]
+			db = cls.getClass(type, 'demeter.db.')
+			connect = db(config).get()
+			model = cls.getClass(table, 'model.')
+			cls.modelObj[table] =  model(type, connect, config)
+		return cls.modelObj[table]
+
+	@classmethod
+	def getClass(cls, name, path=''):
+		obj = cls.getObject(name, path)
+		return getattr(obj, name.capitalize())
+
+	@staticmethod
+	def getObject(name, path = ''):
+		module = __import__(path + name)
+		return getattr(module, name)
+
+	@staticmethod
+	def bool(value):
+		return value == str(True)
+
+	@classmethod
+	def runtime(cls, path, file, content=''):
+		path = cls.path + 'runtime/' + path + '/'
+		File.mkdir(path)
+		file = path + file
+		if File.exists(file):
+			return False
+		else:
+			File.write(file, content)
+			return True
+
+	@classmethod
+	def webstart(cls, name):
+		cls.web = name
+		cls.getObject('main', name + '.')
+
+	@classmethod
+	def md5(cls, value, salt=False):
+		module = __import__('md5')
+		md5 = getattr(module, 'new')
+		md5_obj = md5()
+		if salt:
+			if salt == True:
+				salt = cls.rand()
+			md5_obj.update(value + salt)
+			return md5_obj.hexdigest() + '_' + salt
+		else:
+			md5_obj.update(value)
+			return md5_obj.hexdigest()
+
+	@staticmethod
+	def rand(length = 4):
+		module = __import__('random')
+		rand = getattr(module, 'randint')
+		salt = ''
+		chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
+		len_chars = len(chars) - 1
+		for i in xrange(length):
+			salt += chars[rand(0, len_chars)]
+		return salt
+
+	@staticmethod
+	def mktime(value):
+		module = __import__('time')
+		strptime = getattr(module, 'strptime')
+		mktime = getattr(module, 'mktime')
+		return int(mktime(strptime(value,'%Y-%m-%d %H:%M:%S')))
+
+	@staticmethod
+	def date(value):
+		module = __import__('datetime')
+		datetime = getattr(module, 'datetime')
+		fromtimestamp = getattr(datetime, 'fromtimestamp')
+		return str(fromtimestamp(value).strftime('%Y-%m-%d %H:%M:%S'))
+
+	@staticmethod
+	def error(string):
+		print string
+		os._exit(0)
+
+class File(object):
+
+	@staticmethod
+	def write(file, content):
+		handle = open(file, 'w')
+		handle.write(content)
+		handle.close()
+		Shell.popen('chmod +x ' + file)
+
+	@staticmethod
+	def read(path, name):
+		handle = open(path + name, 'r')
+		content = handle.read()
+		handle.close()
+		return content
+
+	@staticmethod
+	def cur_path():
+		return os.path.split(os.path.realpath(__file__))[0] + '/'
+
+	@staticmethod
+	def path():
+		return os.sys.path[0] + '/'
+
+	@staticmethod
+	def exists(name):
+		return os.path.exists(name)
+
+	@staticmethod
+	def rename(old, new):
+		return os.rename(old, new)
+
+	@staticmethod
+	def remove(file):
+		return os.remove(file)
+
+	@staticmethod
+	def mkdir(path):
+		if File.exists(path) == False:
+			os.mkdir(path)
+		return path
+
+	@staticmethod
+	def mkdirs(path):
+		if File.exists(path) == False:
+			os.makedirs(path)
+		return path
+
+class Shell(object):
+	@staticmethod
+	def popen(command, sub=False, bg=False):
+		string = command
+		if bg == True:
+			command = command + ' 1>/dev/null 2>&1 &'
+		if sub == False:
+			process = os.popen(command)
+			output = process.read()
+			process.close()
+			return output
+		else:
+			popen  = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
+			output = ''
+			print string
+			while True:
+				output = popen.stdout.readline()
+				print output
+				if popen.poll() is not None:
+					break
+			return output
+
+Demeter.initConfig()

+ 6 - 0
db/__init__.py

@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter init
+    author:rabin
+"""

+ 26 - 0
db/influxdb.py

@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter database
+    name:influxdb.py
+    author:rabin
+"""
+from influxdb import InfluxDBClient
+
+class Influxdb(object):
+	instance = None
+	def __new__(cls, *args, **kwd):
+		if Influxdb.instance is None:
+			Influxdb.instance = object.__new__(cls, *args, **kwd)
+		return Influxdb.instance
+
+	def __init__(self, config):
+		self.connect = InfluxDBClient(config['host'], config['port'], config['username'], config['password'], config['dbname'])
+		self.create(config['dbname'])
+
+	def get(self):
+		return self.connect
+
+	def create(self, name):
+		database = self.connect.get_list_database()
+		self.connect.create_database(name)

+ 26 - 0
db/postgresql.py

@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter database
+    name:postgresql.py
+    author:rabin
+"""
+import psycopg2
+
+class Postgresql(object):
+	instance = None
+	def __new__(cls, *args, **kwd):
+		if Postgresql.instance is None:
+			Postgresql.instance = object.__new__(cls, *args, **kwd)
+		return Postgresql.instance
+		
+	def __init__(self, config):
+		self.connect = psycopg2.connect(host=config['host'], port=config['port'], user=config['username'], password=config['password'], database=config['dbname'])
+
+	def get(self):
+		return self.connect
+
+	def create(self, name):
+		'psql -U postgres'
+		sql = 'CREATE DATABASE '+name+' WITH OWNER = postgres ENCODING = "UTF8"'
+		return sql

+ 6 - 0
model/__init__.py

@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter init
+    author:rabin
+"""

+ 239 - 0
model/base.py

@@ -0,0 +1,239 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter database
+    name:__base__.py
+    author:rabin
+"""
+import os
+import uuid
+import short_url
+import json
+import traceback
+import uuid
+import re
+import math
+from sql import *
+from demeter.core import *
+class Base(object):
+	__table__ = ''
+	__comment__ = ''
+	def __init__(self, type, db, config):
+		self.db = db
+		self._type = type
+		self._config = config
+		self._table = self._config['prefix'] + '_' + self.__table__
+		self._set = ''
+		self._bind = {}
+		self._attr = {}
+		self._key = {}
+		self.create()
+
+	def cur(self):
+		return self.db.cursor()
+
+	def query(self, sql, method='select', fetch='fetchall'):
+		cur = self.cur()
+		bind = []
+		if self._set:
+			for key in self._set:
+				if self._set[key] == 'time':
+					self._set[key] = self.time()
+				elif self._set[key] == 'True':
+					self._set[key] = True
+				elif self._set[key] == 'False':
+					self._set[key] = False
+				elif 'date' in key:
+					self._set[key] = self.mktime(self._set[key])
+				bind.append(self._set[key])
+		for value in self._key:
+			if value[0] in self._bind and self._bind[value[0]] != None:
+				val = self._bind[value[0]]
+				self._attr[value[0]].unset()
+				if type(val) == list and val:
+					for i in val:
+						bind.append(i)
+				else:
+					bind.append(val)
+		if method == 'select' and ';' in sql:
+			temp = sql.split(';')
+			sql = temp[1]
+			totalSql = temp[0]
+			cur.execute(totalSql, bind)
+			Demeter.config['page']['totalNum'] = self.fetch(cur, 'fetchone', 'count')
+			Demeter.config['page']['total'] = math.ceil(round(float(Demeter.config['page']['totalNum'])/float(Demeter.config['page']['num']),2))
+		cur.execute(sql, bind)
+		if method == 'select':
+			return self.fetch(cur, fetch)
+		id = True
+		if method == 'insert':
+			id = cur.fetchone()[0]
+		self.db.commit()
+		self._set = {}
+		return id
+		"""
+		try:
+			
+		except Exception, e:
+			print e.message
+			os._exit(0)
+		"""
+
+
+	def fetch(self, cur, type, method = ''):
+		load = getattr(cur, type)
+		rows = load()
+		if type == 'fetchall':
+			result = []
+			if rows:
+				for key in rows:
+					row = {}
+					i = 0
+					for v in key:
+						row[self._key[i][0]] = v
+						i = i + 1
+					result.append(row)
+		elif method == 'count':
+			return rows[0]
+		else:
+			result = {}
+			i = 0
+			if rows:
+				for key in rows:
+					if not key:
+						key = ''
+					result[self._key[i][0]] = key
+					i = i + 1
+		return result
+
+	def attr(self, method):
+		fields = vars(self.__class__)
+		self._attr = {}
+		self._bind = {}
+		self._key = {}
+		col = (int, str, long, float, unicode, bool, uuid.UUID)
+		for field in fields:
+			if isinstance(fields[field], Fields):
+				self._attr[field] = fields[field]
+				self._key[field] = self._attr[field].getKey()
+				insert = (method == 'insert')
+				if insert and self._attr[field].uuid:
+					self.setUuid(field, col)
+				bind = False
+				val = self._attr[field].getArgv()
+				if val:
+					bind = True
+				else:
+					val = getattr(self, field)
+					if isinstance(val, col):
+						setattr(self, field, self._attr[field])
+						bind = True
+					elif insert and self._attr[field].default:
+						val = self._attr[field].default
+						bind = True
+						if val == 'time':
+							val = self.time()
+						elif '.' in val:
+							temp = val.split('.')
+							val = Demeter.config[temp[0]][temp[1]]
+					elif method == 'select' and self._attr[field].default and field == 'state':
+						val = self._attr[field].default
+						bind = True
+				if bind and val:
+					if type(val) == list:
+						length = len(val)
+						if length <= 1:
+							val = val[0]
+					if insert and self._attr[field].md5:
+						val = self.createMd5(val)
+					if self._attr[field].type == 'boolean' and isinstance(val, (str, unicode)):
+						val = Demeter.bool(val)
+					self.check(field, val, self._attr[field])
+					self._bind[field] = val
+					self._attr[field].val(self._bind[field])
+					self._attr[field].bind('%s')
+
+		self._key = sorted(self._key.items(), key=lambda d:d[1], reverse = False)
+		Counter().unset()
+
+	def check(self, field, val, attr):
+		if attr.match == 'not':
+			if not val:
+				Demeter.error(field + ' not exists')
+		elif attr.match:
+			result = re.search(attr.match, val)
+			if not result:
+				Demeter.error(field + ' not match:' + attr.match)
+
+	def time(self):
+		module = __import__('time')
+		time = getattr(module, 'time')
+		return int(time())
+
+	def mktime(self, value):
+		return Demeter.mktime(value)
+
+	def setUuid(self, field, col):
+		id = getattr(self, self._attr[field].uuid)
+		if isinstance(id, col):
+			system = short_url.encode_url(id)
+		else:
+			system = self._attr[field].uuid
+		name = system + '.' + self.__table__
+		result = uuid.uuid5(uuid.uuid1(), name)
+		result = str(result)
+		setattr(self, field, result)
+
+	def createMd5(self, value):
+		return Demeter.md5(value, salt=True)
+
+	def createState(self):
+		create = Demeter.bool(self._config['create'])
+		if create:
+			return Demeter.runtime(self._type, self.__table__, json.dumps(self._key))
+		return False
+
+	def drop(self):
+		return self.handle('drop')
+
+	def create(self):
+		return self.handle('create')
+
+	def insert(self):
+		return self.handle('insert')
+
+	def update(self, *args, **kwargs):
+		if args:
+			self._set = args[0]
+		else:
+			self._set = kwargs
+		return self.handle('update', set=self._set)
+
+	def delete(self):
+		return self.handle('delete')
+
+	def select(self, type='fetchall',col = '*', order = 'cdate desc', group = '', limit = '0,100', page=False):
+		pageConfig = {}
+		if page and 'page' in Demeter.config:
+			pageConfig['current'] = Demeter.config['page']['current']
+			if page == True:
+				pageConfig['num'] = 15
+			elif 'num' in page:
+				pageConfig['num'] = page['num']
+			Demeter.config['page']['num'] = pageConfig['num']
+		return self.handle('select', type=type, col=col, order=order, group=group, limit=limit, page=pageConfig)
+
+	def manage(self):
+		self.attr(method)
+		return
+
+	def handle(self, method='select', type='fetchall', col = '*', order = '', group = '', limit = '0,100', page=False, set = ''):
+		self.attr(method)
+		if method == 'create':
+			create = self.createState()
+			if create == False:
+				return False
+		if type == 'fetchone':
+			limit = '0,1'
+		load = getattr(Sql(self._type), method)
+		return self.query(load(self._table, {'key':self._key, 'fields':self._attr, 'col':col, 'order':order, 'group':group, 'limit':limit, 'page':page, 'set':set, 'table_comment':self.__comment__}), method, type)

+ 382 - 0
model/sql.py

@@ -0,0 +1,382 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter database
+    name:__sql__.py
+    author:rabin
+"""
+from demeter.core import *
+class Fields(object):
+	def __init__(self, type='', default='', primaryKey=False, autoIncrement=False, null=True, unique=False, check='', constraint='', comment='', uuid='', index=False, indexs=False, md5=False, match='', manage=''):
+		self.type = type
+		self.default = default
+		self.primaryKey = primaryKey
+		self.autoIncrement = autoIncrement
+		self.null = null
+		self.unique = unique
+		self.check = check
+		self.constraint = constraint
+		self.comment = comment
+		self.uuid = uuid
+		self.index = index
+		self.indexs = indexs
+		self.md5 = md5
+		self.key = Counter().inc()
+		self.match = match
+		self.value = ''
+		self.argv = ''
+		self.bindValue = ''
+		self.expValue = '='
+		self.logicValue = 'and'
+		self.manage = manage
+
+
+	def assgin(self, value, exp='=', logic='and'):
+		self.add(value)
+		self.exp(exp)
+		self.logic(logic)
+		return self
+
+	def bind(self, value):
+		self.bindValue = value
+		return self
+
+	def exp(self, value):
+		if type(self.expValue) != list:
+			self.expValue = []
+		self.expValue.append(value)
+		return self
+
+	def logic(self, value):
+		if type(self.logicValue) != list:
+			self.logicValue = []
+		self.logicValue.append(value)
+		return self
+
+	def val(self, value, exp='=', logic='and'):
+		if type(value) == list:
+			length = len(value)
+			if length <= 1:
+				value = value[0]
+		self.value = value
+		if not self.expValue:
+			self.exp(exp)
+		if not self.logicValue:
+			self.logic(logic)
+		return self
+
+	def getArgv(self):
+		return self.argv
+
+	def getVal(self):
+		return self.value
+
+	def getBind(self):
+		return self.bindValue
+
+	def getExp(self):
+		if not self.expValue:
+			return ''
+		if type(self.expValue) == list:
+			length = len(self.expValue)
+			if length <= 1:
+				result = self.expValue[0]
+			else:
+				result = self.expValue
+		else:
+			result = self.expValue
+		return result
+
+	def getKey(self):
+		return self.key
+
+	def getLogic(self):
+		if not self.logicValue:
+			return ''
+		if type(self.logicValue) == list:
+			length = len(self.logicValue)
+			if length <= 1:
+				result = self.logicValue[0]
+			else:
+				result = self.logicValue
+		else:
+			result = self.logicValue
+		return result
+
+	def unset(self):
+		self.argv = None
+		self.value = None
+		self.bindValue = None
+		self.expValue = '='
+		self.logicValue = 'and'
+		return self
+
+	def add(self, value):
+		if not self.argv:
+			self.argv = []
+		self.argv.append(value)
+		return self
+
+	def ins(self, value):
+		self.argv = value
+		self.exp('in')
+		return self
+
+	def nq(self, value):
+		self.argv = value
+		self.exp('!=')
+		return self
+
+	def like(self, value):
+		self.argv = '%' + value + '%'
+		self.exp('like')
+		return self
+
+	def mlike(self, value):
+		self.argv = value
+		self.exp('~')
+		self.logic('and')
+		return self
+
+	def time(self, value):
+		self.add(Demeter.mktime(value))
+		return self
+
+	def start(self, value):
+		self.time(value)
+		self.exp('>=')
+		self.logic('and')
+		return self
+
+	def end(self, value):
+		self.time(value)
+		self.exp('<=')
+		self.logic('and')
+		return self
+
+class Counter(object):
+	num = 0
+	instance = None
+
+	def __new__(cls, *args, **kwd):
+		if Counter.instance is None:
+			Counter.instance = object.__new__(cls, *args, **kwd)
+		return Counter.instance
+
+	def inc(self):
+		self.num = self.num + 1
+		return self.num
+
+	def dec(self):
+		self.num = self.num - 1
+		return self.num
+
+	def unset(self):
+		self.num = 0
+		return self.num
+
+class Sql(object):
+	instance = None
+	def __new__(cls, *args, **kwd):
+		if Sql.instance is None:
+			Sql.instance = object.__new__(cls, *args, **kwd)
+		return Sql.instance
+
+	def __init__(self, type):
+		self.type = type
+
+	def drop(self, table, args):
+		sql = 'DROP TABLE IF EXISTS ' + table
+		return sql
+
+	def alter(self, table, args):
+		sql = 'ALTER TABLE ' + table + ' ADD COLUMN '
+		return sql
+
+	def create(self, table, args):
+		create = []
+		primary = []
+		unique = []
+		indexs = []
+		index = []
+		comment = {}
+		for value in args['key']:
+			key = value[0]
+			val = args['fields'][key]
+			if val.primaryKey:
+				primary.append(key)
+			if val.unique:
+				unique.append(key)
+			if val.index:
+				index.append((key, val.index))
+			if val.indexs:
+				indexs.append(key)
+
+			fields = []
+			fields.append(key)
+			if val.autoIncrement and self.type == 'postgresql':
+				fields.append('SERIAL')
+			else:
+				fields.append(val.type)
+
+			if not val.null:
+				fields.append('NOT NULL')
+				
+
+			if val.autoIncrement and self.type == 'mysql':
+				fields.append('AUTO_INCREMENT')
+
+			#约束
+			if val.constraint:
+				fields.append('CONSTRAINT ' + val.constraint)
+			if val.check:
+				fields.append('CHECK ' + val.check)
+			
+			if val.default:
+				default = val.default
+				if val.default == 'time':
+					default = '0'
+				if '.' in val.default:
+					temp = val.default.split('.')
+					default = Demeter.config[temp[0]][temp[1]]
+				fields.append('DEFAULT \'' + str(default) + '\'')
+
+			if val.comment:
+				if self.type == 'mysql':
+					fields.append('COMMENT \'' + val.comment + '\'')
+				else:
+					comment[key] = val.comment
+
+			fields = ' '.join(fields)
+			create.append(fields)
+
+		if primary:
+			create.append('PRIMARY KEY (' + ','.join(primary) + ')')
+		if unique:
+			create.append('UNIQUE (' + ','.join(unique) + ')')
+
+		create = ','.join(create)
+		sql = 'CREATE TABLE ' + table + '(' + create + ')'
+		sql = self.drop(table, args) + ';' + sql
+		if indexs:
+			name = '_'.join(indexs)
+			value = ','.join(indexs)
+			sql = sql + ';' + 'CREATE INDEX ' + table + '_' + name +' ON ' + table + '(' + value + ')'
+
+		if index:
+			for value in index:
+				sql = sql + ';' + 'CREATE INDEX ' + table + '_' + value[0] +' ON ' + table + value[1]
+
+		if comment:
+			if args['table_comment']:
+				sql = sql + ';' + 'COMMENT ON TABLE ' + table + ' IS \''+args['table_comment']+'\''
+			for key in comment:
+				sql = sql + ';' + 'COMMENT ON COLUMN ' + table + '.'+key+' IS \''+comment[key]+'\''
+		return sql
+
+	def insert(self, table, args):
+		fields = []
+		values = []
+		for value in args['key']:
+			key = value[0]
+			val = args['fields'][key].getBind()
+			if val:
+				values.append(val)
+				fields.append(key)
+
+		fields = ','.join(fields)
+		values = ','.join(values)
+		sql = 'INSERT INTO ' + table + ' (' + fields + ') VALUES (' + values + ')'
+		if self.type == 'postgresql':
+			sql = sql + ' RETURNING id'
+		return sql
+
+	def update(self, table, args):
+		fields = []
+		for key in args['set']:
+			fields.append(key + ' = %s')
+
+		fields = ','.join(fields)
+		sql = 'UPDATE ' + table + ' SET ' + fields + self.where(args['key'], args['fields'])
+		return sql
+
+	def delete(self, table, args):
+		sql = 'DELETE FROM ' + table + self.where(args['fields'])
+		return sql
+
+	def select(self, table, args):
+		string = ' FROM ' + table + self.where(args['key'], args['fields']) + ' ' + self.group(args['group'])
+		sql = ''
+		if args['page']:
+			sql = 'SELECT count(1) as total' + string + ';'
+		sql = sql + 'SELECT ' + args['col'] + string + ' ' + self.order(args['order']) + ' ' + self.limit(args['limit'], args['page'])
+		return sql
+
+	def where(self, key, fields):
+		fields = self.fields(key, fields)
+		if fields:
+			return ' WHERE ' + fields
+		return ''
+
+	def fields(self, key, fields):
+		result = ''
+		k = 0
+		for value in key:
+			key = value[0]
+			field = fields[key]
+			bind = field.getBind()
+			val = field.getVal()
+			logic = field.getLogic()
+			exp = field.getExp()
+			if type(val) == list and val:
+				n = 0
+				for i in val:
+					data = self.field(field, bind, key, k, logic[n], exp[n])
+					n = n + 1
+					if data:
+						result = result + data
+						k = 1
+			else:
+				data = self.field(field, bind, key, k, logic, exp)
+				if data:
+					result = result + data
+					k = 1
+		return result
+
+	def field(self, field, val, key, k, logic, exp):
+		result = ''
+		if val:
+			if k == 0:
+				logic = ''
+			else:
+				logic = ' ' + logic
+			result = logic + ' ' + key + ' ' + exp + ' ' + str(val)
+		return result
+
+	def order(self, value):
+		result = ''
+		if value:
+			result = ' ORDER BY ' + value
+
+		return result
+
+	def group(self, value):
+		result = ''
+		if value:
+			result = ' GROUP BY ' + value
+
+		return result
+
+	def limit(self, value, page):
+		result = ''
+		if page:
+			value = str((int(page['current'])-1) * page['num']) + ',' + str(page['num'])
+		if value:
+			value = value.split(',')
+			if self.type == 'mysql':
+				result = ' LIMIT ' + value[0] + ',' + value[1]
+			elif self.type == 'postgresql':
+				result = ' LIMIT ' + value[1] + ' OFFSET ' + value[0]
+
+		return result
+

+ 6 - 0
mqtt/__init__.py

@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter init
+    author:rabin
+"""

+ 49 - 0
mqtt/connect.py

@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter mqtt
+    name:connect.py
+    author:rabin
+"""
+from demeter.core import *
+import paho.mqtt.client as mqtt
+#from gevent import monkey; monkey.patch_all()
+#import gevent
+
+class Connect(object):
+
+	def __init__(self, act):
+		act.connect = self
+		self.client = mqtt.Client()
+		self.client.on_connect = self.connect
+		state = hasattr(act, 'message')
+		if state:
+			self.client.on_message = act.message
+		self.client.connect(Demeter.config['mqtt']['host'], Demeter.config['mqtt']['port'], int(Demeter.config['mqtt']['timeout']))
+		if state:
+			self.client.loop_forever()
+
+	def __del__(self):
+		pass
+
+	def getClient(self):
+		return self.client
+
+	def connect(self, client, userdata, flags, rc):
+		#print("Connected with result code "+str(rc))
+		#client.subscribe("sensor/#")
+		client.subscribe("pic/#")
+		"""
+		gevent.joinall([
+			gevent.spawn(self.subscribe, client, 'sensor/#'),
+			gevent.spawn(self.subscribe, client, 'pic/#'),
+			gevent.spawn(self.subscribe, client, 'msg/#'),
+		])
+		"""
+
+	@staticmethod
+	def subscribe(client, key):
+		client.subscribe(key)
+
+	def handle(self, key, value):
+		Demeter.record(key, value)

+ 19 - 0
mqtt/pub.py

@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter mqtt
+    name:pub.py
+    author:rabin
+"""
+from connect import Connect
+
+class Pub(object):
+
+	def __init__(self):
+		Connect(self)
+
+	def __del__(self):
+		pass
+
+	def push(self, key, msg):
+		self.connect.getClient().publish(key,msg)

+ 20 - 0
mqtt/sub.py

@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter mqtt
+    name:sub.py
+    author:rabin
+"""
+from connect import Connect
+
+class Sub(object):
+
+	def __init__(self):
+		Connect(self)
+
+	def __del__(self):
+		pass
+
+	def message(self, client, userdata, msg):
+		#print(msg.topic+" "+str(msg.payload))
+		self.connect.handle(msg.topic, str(msg.payload))

+ 6 - 0
tcp/__init__.py

@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter init
+    author:rabin
+"""

+ 24 - 0
tcp/client.py

@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+	demeter tcp
+	name:client.py
+	author:rabin
+"""
+import socket  
+import time  
+HOST = '0.0.0.0'	# The remote host  
+PORT = 8000		   # The same port as used by the server  
+s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
+s.connect((HOST, PORT))  
+  
+s.sendall('Hello, \nw')  
+time.sleep(5)  
+s.sendall('ord! \n')  
+  
+data = s.recv(1024)  
+  
+print 'Received', repr(data)  
+  
+time.sleep(60)  
+s.close() 

+ 49 - 0
tcp/server.py

@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+	demeter tcp
+	name:server.py
+	author:rabin
+"""
+from demeter.core import *
+from tornado.tcpserver import TCPServer
+from tornado.ioloop  import IOLoop
+
+class Connection(object):
+	clients = set()
+	def __init__(self, stream, address):
+		Connection.clients.add(self)
+		self._stream = stream
+		self._address = address
+		self._stream.set_close_callback(self.on_close)
+		self.read_message()
+		
+	def read_message(self):
+		self._stream.read_until('\n', self.broadcast_messages)
+	
+	def broadcast_messages(self, data):
+		pub = Pub()
+		temp = data.split(':')
+		key = temp[0]
+		value = temp[1]
+		pub.push(key, value)
+		
+		#print "User said:", data[:-1], self._address
+		"""
+		for conn in Connection.clients:
+			conn.send_message(data)
+		"""
+		self.read_message()
+		
+	def send_message(self, data):
+		self._stream.write(data)
+			
+	def on_close(self):
+		#print "A user has left the chat room.", self._address
+		Connection.clients.remove(self)
+	
+class Server(TCPServer):	
+	def handle_stream(self, stream, address):
+		#print "New connection :", address, stream
+		Connection(stream, address)
+		#print "connection num is:", len(Connection.clients)

+ 6 - 0
web/__init__.py

@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter init
+    author:rabin
+"""

+ 35 - 0
web/api.py

@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter init
+    author:rabin
+"""
+import os
+from demeter.core import *
+
+def loadFile():
+	path = Demeter.path + Demeter.web + '/page/'
+	files = os.listdir(path)
+	result = []
+	for key in files:
+		if '.DS_Store' not in key and  '__' not in key and 'pyc' not in key:
+			key = key.replace('.py', '')
+			result.append(key)
+	return result
+
+def loadUrl(module, key, url):
+	str = dir(module)
+	for i in str:
+		act = ''
+		if '_path' in i:
+			act = i.replace('_path', '')
+		if '_html' in i:
+			act = i.replace('_html', '.html')
+		if act:
+			attr = getattr(module, i)
+			if key == 'main' and act == 'index':
+				url.append((r'/', attr))
+			elif key == act:
+				url.append((r'/'+act, attr))
+			url.append((r'/'+key+'/'+act, attr))
+	return url

+ 49 - 0
web/application.py

@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter web
+    name:application.py
+    author:rabin
+"""
+from demeter.core import *
+import tornado.web
+import tornado.ioloop
+import tornado.httpserver
+
+def start(url):
+    config = Demeter.config[Demeter.web]
+    settings = {
+        "static_path": os.path.join(os.path.dirname(__file__), "static"),
+        "template_path": os.path.join(os.path.dirname(__file__), 'templates'),
+        "cookie_secret": "61oETzKXQAGaYekL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=",
+        "login_url": "/user/login",
+        "xsrf_cookies": True,
+        "debug": Demeter.bool(config['debug']),
+        #"autoreload": Demeter.bool(config['autoreload']),
+        "port": config['port'],
+        "max_buffer_size": int(config['max_buffer_size']),
+        "process": int(config['process'])
+    }
+    handlers = []
+    def application_setting():
+        handlers.append((r"/upload/(.*)", tornado.web.StaticFileHandler, {"path": Demeter.path + 'runtime/upload/'}))
+        handlers.append((r"/static/(.*)", tornado.web.StaticFileHandler, {"path":"static"}))
+        handlers.append((r"/(apple-touch-icon\.png)", tornado.web.StaticFileHandler, dict(path=settings['static_path'])))
+        handlers.extend(url)
+
+    application_setting()
+    application = tornado.web.Application(handlers=handlers, **settings)
+    
+    if settings['debug'] == True:
+        application.listen(settings['port'])
+        tornado.ioloop.IOLoop.instance().start()
+    else:
+        server = tornado.httpserver.HTTPServer(application, settings['max_buffer_size'])
+        server.bind(settings['port'])
+        server.start(settings['process'])
+        try:        
+            print 'running on port %s' % settings['port']
+            tornado.ioloop.IOLoop.instance().start()
+
+        except KeyboardInterrupt:
+            tornado.ioloop.IOLoop.instance().stop()

+ 161 - 0
web/base.py

@@ -0,0 +1,161 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter load
+    author:rabin
+"""
+import tornado.web
+from demeter.core import *
+import json
+
+class Base(tornado.web.RequestHandler):
+	def initialize(self):
+		self.data = {}
+		self.page()
+		self.search()
+		self.cookie()
+		self.setting()
+		self.assign()
+
+	def get_current_user(self):
+		return self.get_secure_cookie(self.KEYS[1])
+
+	def assign(self):
+		self.data['setting'] = Demeter.config['setting']
+		
+	def cookie(self):
+		for key in self.KEYS:
+			cookie = None
+			if key in Demeter.config['base']:
+				cookie = Demeter.config['base'][key]
+			if not cookie:
+				cookie = self.get_secure_cookie(key)
+				#cookie = self.get_cookie(key)
+			if not cookie:
+				value = self.input(key)
+				if value:
+					#self.set_secure_cookie(key, value)
+					Demeter.config['setting'][key] = value
+				else:
+					Demeter.config['setting'][key] = 0
+			else:
+				Demeter.config['setting'][key] = cookie
+
+	def page(self):
+		Demeter.config['page'] = {}
+		page = self.input('page')
+		if page:
+			Demeter.config['page']['ajax'] = True
+		else:
+			Demeter.config['page']['ajax'] = False
+			page = 1
+		Demeter.config['page']['current'] = page
+		Demeter.config['page']['total'] = 0
+		self.data['page'] = Demeter.config['page']
+
+	def search(self):
+		data = self.request.arguments
+		self.data['search'] = {}
+		self.data['update'] = {}
+		for key in data:
+			if 'search_' in key:
+				index = key.replace('search_', '')
+				self.data['search'][index] = ",".join(data[key])
+			if 'update_' in key:
+				index = key.replace('update_', '')
+				self.data['update'][index] = ",".join(data[key])
+
+	def input(self, key, value=None):
+		return self.get_argument(key, value)
+
+	def service(self, name):
+		return Demeter.service(name)
+
+	def model(self, name):
+		return Demeter.model(name)
+
+	def common(self, **kwd):
+		self.data['common'] = kwd
+		farm = str(Demeter.config['setting']['farm'])
+		self.data['common']['argvs'] = '&farm=' + farm + '&search_farm_id-select-=' + farm
+
+	def commonView(self, name):
+		self.view('common/'+name+'.html')
+
+	def commonList(self, model):
+		self.data['state'] = self.input('state', True)
+		self.data['list'] = self.service('common').list(model, state=self.data['state'], search=self.data['search'], page=True)
+
+	def commonOne(self, model, **kwd):
+		id = self.input('id')
+		self.data['info'] = {}
+		if id:
+			kwd['id'] = id
+		if kwd:
+			self.data['info'] = self.service('common').one(model, **kwd)
+		if not self.data['info'] and Demeter.config['setting']['farm'] > 0:
+			self.data['info']['farm_id'] = Demeter.config['setting']['farm']
+
+	def commonUpdate(self, model, msg='', id=0, **kwd):
+		if not self.data['auth']:
+			self.auth()
+		else:
+			if id <= 0:
+				id = self.input('id')
+			if kwd:
+				info = self.service('common').one(model, **kwd)
+				if id:
+					id = int(id)
+				if info and (id != info['id']):
+					self.out(msg)
+					return
+			state = self.service('common').update(model, id, self.data['update'])
+			self.log(model, 'update', self.data['update'])
+			self.out('yes', {'id':state})
+			return state
+
+	def commonDelete(self, model):
+		if not self.data['auth']:
+			self.auth()
+		else:
+			id = self.input('id')
+			state = self.input('state', False)
+			state = self.service('common').delete(model, id, state)
+			self.log(model, 'delete', {id:id, state:state})
+			self.out('yes', {'state':state})
+
+	def log(self, model, method, data):
+		insert = {}
+		insert['admin_id'] = Demeter.config['setting']['admin']
+		insert['model'] = model
+		insert['method'] = method
+		insert['data'] = json.dumps(data)
+		self.service('common').update('manage_log', None, insert)
+
+	def view(self, name):
+		if not self.data['auth']:
+			self.auth()
+		else:
+			self.render(name, data=self.data)
+
+	def auth(self):
+		self.out('您没有权限')
+
+	def out(self, msg='', data={}, code=0):
+		callback = self.input('callback')
+		function = self.input('function')
+		result = ''
+		send = {}
+		send['status'] = 1
+		send['msg'] = msg
+		send['data'] = data
+		send['code'] = code
+		if not send['data']:
+			send['status'] = 2
+		result = json.dumps(send)
+		if callback:
+			result = callback + '(' + result + ')'
+		elif function:
+			result = '<script>parent.' + function + '(' + result + ')' + '</script>';
+		self.write(result)
+		#self.finish(result)