class EditModel(RestView): """ A view that allows models to be edited. Takes the class name as a string parameter and returns the correct html form. """ def __init__(self, request): self.request = request self.session = DBSession() self.cls = self.look_up_class() self.instance = self.look_up_instance() self.breadcrumbs = breadcrumbs[:] self.breadcrumbs.append({'text': 'Edit %s' % self.instance}) def get(self): fs = FieldSet(self.instance) return {'fs': fs, 'breadcrumbs': self.breadcrumbs[:], 'instance': self.instance, 'cls': self.cls} def post(self): fs = FieldSet(self.instance, data=self.request.POST) if fs.validate(): fs.sync() self.session.flush() return HTTPFound(location=fs.model.getUrl())
def update_tokens(self): """ We need to record these updates to token states and provide a way to view this in the Gateway Interface. """ session = DBSession() data = simplejson.loads(self.request.body) if not 'device_id' in data: return json_response('You must provide an device_id') device = session.query(Device)\ .filter_by(device_id=data['device_id']).first() if device: for i in data['tokens']: token = session.query(Token)\ .filter_by(token=i['token_id']).first() if token: circuit = session.query(Circuit)\ .filter_by(pin=i['account_id']).first() if circuit: job = AddCredit(token.value, circuit, token) session.add(job) token.state = 'used' session.merge(token) session.flush() return json_response('ok') else: return json_response('You must provide a valid device_id')
def make_tokens(self): session = DBSession() batch = TokenBatch() session.add(batch) session.flush() data = simplejson.loads(self.request.body) if not 'device_id' in data: return Response('You must provide an device_id') else: device = session.query(Device)\ .filter_by(device_id=data['device_id']).first() if device: if not 'tokens' in data: return Response('You must provide an amount of tokens') for group in data['tokens']: for i in range(0, group['count']): token = Token(Token.get_random(), batch=batch, value=group['denomination']) session.add(token) session.flush() return json_response( [{'token_id': int(token.token), 'denomination': float(token.value)} for token in batch.getTokens()]) else: return json_response('Not a valid device')
def login(self): session = DBSession() came_from = self.request.params.get('came_from', '/') message = '' login = '' password = '' if 'form.submitted' in self.request.params: name = self.request.params['name'] hash = hashlib.md5(self.request.params['password']).hexdigest() user = session.query(Users)\ .filter_by(name=name)\ .filter_by(password=unicode(hash)).first() if user: print(name, hash) headers = remember(self.request, user.name) return HTTPFound( location="%s" % came_from, headers=headers) message = 'Failed login' return { 'message': message, 'url': self.request.application_url + '/login', 'came_from': came_from, 'login': login, 'password': password}
class MessageHandler(object): def __init__(self, request): self.session = DBSession() self.request = request self.message = self.session.\ query(Message).filter_by( uuid=self.request.matchdict["id"]).first() @action(renderer='sms/index_msg.mako') def index(self): global breadcrumbs breadcrumbs.extend({}) return { 'breadcrumbs': breadcrumbs, 'message': self.message } @action(request_method="POST") def remove(self): self.message.sent = True self.session.merge(self.message) return Response("ok") @action(renderer='sms/delete_msg.mako') def delete(self): if self.request.method == 'POST': return Response("Removed Message") elif self.request.method == 'GET': return {'message': self.message }
class AddClass(RestView): """ An genertic view that allows for adding models to our system. """ def __init__(self, request): self.request = request self.session = DBSession() self.cls = self.look_up_class() self.breadcrumbs = breadcrumbs[:] self.breadcrumbs\ .append({'text': 'Add a new %s' % self.cls.__name__}) def get(self): fs = FieldSet(self.cls, session=self.session) return { 'breadcrumbs': self.breadcrumbs, 'fs': fs, 'cls': self.cls} def post(self): fs = FieldSet(self.cls, session=self.session).\ bind(self.cls(), data=self.request.POST) if fs.validate(): fs.sync() self.session.flush() return HTTPFound(location=fs.model.getUrl()) else: return {'fs': fs, 'cls': self.cls}
def send(self): session = DBSession() twilio = session.query(TwilioInterface).first() msg = save_and_parse_message(twilio, self.request.params['From'], self.request.params['Body'], id=self.request.params['SmsMessageSid']) return Response(msg.uuid)
class SMSHandler(object): """ Handler for most SMS operations """ def __init__(self, request): self.request = request self.breadcrumbs = breadcrumbs[:] self.session = DBSession() @action(renderer="sms/index.mako", permission="view") def index(self): breadcrumbs = self.breadcrumbs[:] breadcrumbs.append({"text": "SMS Message"}) limit = self.request.params.get('limit', 1000) count = self.session.query(Message).count() messages = self.session.\ query(Message).order_by(desc(Message.id)).limit(limit) return { "limit": limit, "count": count, "messages": messages, "table_headers": make_table_header(OutgoingMessage), "breadcrumbs": breadcrumbs} @action(renderer='sms/meter_messages.mako', permission='view') def meter_messages(self): from sqlalchemy import create_engine db_string = self.request.registry.settings.get('db_string') engine = create_engine(db_string, echo=False) conn = engine.connect() results = conn.execute( """ SELECT meter.name, meter.id, incoming_message.text, message.date FROM meter, message, incoming_message WHERE meter.phone = message.number AND message.id = incoming_message.id ORDER BY message.date DESC LIMIT 1000; """) return {'results': results} @action(permission="view") def remove_all(self): [self.session.delete(msg) for msg in self.session.query(Message).all()] return HTTPFound( location="%s/sms/index" % self.request.application_url) @action() def ping(self): return Response('ok') @action() def received(self): msgs = [msg.toDict() for msg in self.session.query(Message).\ filter_by(sent=False).filter(or_(Message.type == "job_message", Message.type == "outgoing_message")).all() if msg.number != ''] return Response( content_type="application/json", body=simplejson.dumps(msgs))
def findMeter(message): """ Takes a message object and returns either a meter or none. Looks up the meter based on the message's number. """ session = DBSession() meter = session.query(Meter).filter_by(phone=str(message.number)).first() if meter: return meter
def groupfinder(userid, request): """ Rough cut of user admin system. """ session = DBSession() user = session.query(Users).filter_by(name=userid).first() if user: if user.group: return [user.group.name]
def job(self): session = DBSession() job = session.query(Job).get(self.request.matchdict["id"]) if self.request.method == "DELETE": job.state = False job.end = datetime.now() session.merge(job) return Response(str(job)) else: return Response(simplejson.dumps(job.toDict()))
def save_and_parse_message(interface, origin, text, id=None): """ """ session = DBSession() if id is None: id = str(uuid.uuid4()) message = IncomingMessage(origin, text, id, interface) session.add(message) session.flush() dispatcher.matchMessage(message) return message
def findCircuit(message, meter): """Looks up circuit from meter and message. """ session = DBSession() try: circuit = session.query(Circuit).\ filter_by(ip_address=message["cid"]).\ filter_by(meter=meter).first() if circuit: return circuit except Exception as e: print e, message
def get_token(message): """Tries to match message to token.""" session = DBSession() tokenNumber = message.text.split(delimiter)[2] token = session.query(Token).filter_by(state="new").filter_by(token=tokenNumber).first() if token: return token else: interface = message.communication_interface interface.sendMessage( message.number, make_message_body("no-token.txt", lang=message.langauge), incoming=message.uuid ) return False
def show_pculogs(self): session = DBSession() value = self.request.params.get('pcu-value', 'battery_volts') start = datetime.strptime( self.request.params.get('start', '05/01/2011'), '%m/%d/%Y') end = datetime.strptime( self.request.params.get('end', '07/20/2011'), '%m/%d/%Y') pculogs = session.query(PCULog)\ .filter(PCULog.meter == self.meter)\ .filter(PCULog.timestamp >= start)\ .filter(PCULog.timestamp <= end) return json_response( {'dates': map(lambda x: time.mktime(x.timestamp.timetuple()), pculogs), 'values': map(lambda x: getattr(x, value), pculogs)})
def show_primary_logs(self): session = DBSession() logs = session.query(PrimaryLog)\ .filter_by(circuit=self.circuit)\ .order_by(desc(PrimaryLog.created))\ .limit(200) return json_response([{'id': l.id, 'status': l.status, 'use_time': l.use_time, 'gateway_date': l.created.strftime('%Y-%m-%d %H:%M:%S'), 'meter_date': l.date.strftime('%Y-%m-%d %H:%M:%S'), 'time_difference': find_time_different(l), 'watthours': "{0:.1f}".format(l.watthours), 'credit': int(l.credit)} for l in logs])
def get_circuit(message): """Queris the database to find circuit Returns the circuit or false """ session = DBSession() pin = message.text.split(delimiter)[1].lower() circuit = session.query(Circuit).filter_by(pin=pin).first() if circuit: return circuit else: interface = message.communication_interface interface.sendMessage( message.number, make_message_body("no-circuit.txt", lang=interface.lang, pin=pin), incoming=message.uuid)
def metersAsGeoJson(self): session = DBSession() meters = session.query(Meter).filter(Meter.geometry != None) return Response( content_type='application/json', body=simplejson.dumps( {'type': 'FeatureCollection', 'features': [{'type': 'Feature', 'properties': {'name': x.name}, 'geometry': {'type': 'Point', 'coordinates': list(loads( x.geometry).coords)[0]}} for x in meters] }))
def get_payment_logs(self): """ A view to render a circuit's payment history as a json object. """ session = DBSession() payments = session.query(AddCredit)\ .filter_by(circuit=self.circuit).order_by(desc(AddCredit.start)) return json_response( {'payments': [{'id': p.id, 'status': p.state, 'token': str(p.token), 'start': str(p.start), 'credit': p.credit, 'end': str(p.end), 'state': p.state} for p in payments]})
def set_primary_contact(message): """Allows users to set their primary contact number""" session = DBSession() circuit = get_circuit(message) if circuit: interface = circuit.meter.communication_interface new_number = message.text.split(delimiter)[2] old_number = circuit.account.phone messageBody = make_message_body("tel.txt", lang=message.langauge, old_number=old_number, new_number=new_number) interface.sendMessage(message.number, messageBody, incoming=message.uuid) if new_number != message.number: interface.sendMessage(new_number, messageBody, incoming=message.uuid) account = circuit.account account.phone = new_number session.merge(account)
def __init__(self, request): self.session = DBSession() self.request = request self.circuit = self.session.\ query(Circuit).get(self.request.matchdict["id"]) self.meter = self.circuit.meter self.breadcrumbs = breadcrumbs[:]
def show_meters_json(self): session = DBSession() return json_response( [ {'name': m.name, 'id': m.id, 'number_of_circuits': len(m.get_circuits()), 'uptime': find_meter_uptime(m), 'pv': m.panel_capacity, 'last_message': find_last_message_by_meter(m), 'phone': m.phone, 'battery': m.battery, 'location': m.location } for m in session.query(Meter).all() ] )
def find_meter_uptime(meter): """ cs = # of circuits actual = number messages it did receive possible = Number of messages it should have receive in the last week -> 48 * cs * 7 (* (/ actual possible) 100) """ now = datetime.now() last_week = now - timedelta(days=7) session = DBSession() log_count = session.query(PrimaryLog)\ .filter_by(circuit=meter.getMainCircuit())\ .filter(PrimaryLog.date < now)\ .filter(PrimaryLog.date > last_week).count() return int((log_count / (24 * 7.0)) * 100)
def __init__(self, request): self.request = request self.session = DBSession() self.cls = self.look_up_class() self.instance = self.look_up_instance() self.breadcrumbs = breadcrumbs[:] self.breadcrumbs.append({'text': 'Edit %s' % self.instance})
def __init__(self, request): self.request = request self.session = DBSession() self.cls = self.look_up_class() self.breadcrumbs = breadcrumbs[:] self.breadcrumbs\ .append({'text': 'Add a new %s' % self.cls.__name__})
def index(self): """ Main view for meter overview. Also includes circuit gird and some graphs """ session = DBSession() breadcrumbs = self.breadcrumbs[:] breadcrumbs.append({'text': 'Meters', 'url': '/manage/show_meters'}) breadcrumbs.append({"text": "Meter Overview"}) return { 'meter': self.meter, 'last_message': find_last_message_by_meter(self.meter), 'changesets': session\ .query(MeterChangeSet).filter_by(meter=self.meter), 'meter_config_keys': session.query(MeterConfigKey).all(), 'breadcrumbs': breadcrumbs}
def setUp(self): from pyramid.config import Configurator from gateway.models import initialize_sql self.session = initialize_sql('sqlite://') self.config = Configurator(autocommit=True) self.config.begin() from gateway.models import DBSession self.session = DBSession()
def pp(self): """ Primary log action. Should force the meter to provide authentication """ params = parse_qs(self.request.body) session = DBSession() if not self.meter or not self.circuit: return Response(status=404) log = PrimaryLog(circuit=self.circuit, watthours=params["wh"][0], use_time=params["tu"][0], credit=params["cr"][0], status=int(params["status"][0])) self.circuit.credit = float(log.credit) self.circuit.status = int(params["status"][0]) # fix session.add(log) session.merge(self.circuit) return Response("ok")
class SMSHandler(object): """ Handler for most SMS operations """ def __init__(self, request): self.request = request self.breadcrumbs = breadcrumbs[:] self.session = DBSession() @action(renderer="sms/index.mako", permission="admin") def index(self): breadcrumbs = self.breadcrumbs[:] breadcrumbs.append({"text": "SMS Message"}) limit = self.request.params.get('limit', 1000) count = self.session.query(Message).count() messages = self.session.\ query(Message).order_by(desc(Message.id)).limit(limit) return { "logged_in": authenticated_userid(self.request), "limit": limit, "count": count, "messages": messages, "table_headers": make_table_header(OutgoingMessage), "breadcrumbs": breadcrumbs } @action(permission="admin") def remove_all(self): [self.session.delete(msg) for msg in self.session.query(Message).all()] return HTTPFound( location="%s/sms/index" % self.request.application_url) @action() def ping(self): return Response('ok') @action() def received(self): msgs = [msg.toDict() for msg in self.session.query(Message).\ filter_by(sent=False).filter(or_(Message.type == "job_message", Message.type == "outgoing_message")).all() if msg.number != ''] return Response( content_type="application/json", body=simplejson.dumps(msgs))
class FunctionalTests(unittest.TestCase): """ Unit tests for the Gateway UI """ def setUp(self): self.config = testing.setUp() import ConfigParser from gateway.models import DBSession from gateway.models import initialize_sql config = ConfigParser.ConfigParser() config.readfp(open('testing.ini')) db_string = config.get('app:gateway', 'db_string') initialize_sql(db_string) from gateway import main from webtest import TestApp app = main(None, **{'db_string': db_string, 'mako.directories': config.get('app:gateway', 'mako.directories')}) self.testapp = TestApp(app) self.session = DBSession() def tearDown(self): testing.tearDown() def test_number_of_meter(self): from gateway.models import Meter meters = self.session.query(Meter).all() self.assertEquals(len(meters), 1) def test_index(self): res = self.testapp.get('/', status=200) self.assertEquals(res.status, '200 ok') def test_number_of_circuits(self): from gateway.models import Circuit circuits = self.session.query(Circuit).all() self.assertEquals(len(circuits), 11) def test_number_of_comm_interfaces(self): from gateway.models import CommunicationInterface interfaces = self.session.query(CommunicationInterface).all() self.assertEquals(len(interfaces), 1) def test_balance_english(self): from gateway.models import CommunicationInterface from gateway.models import Circuit