Skip to content

Commit

Permalink
implemented payouts and sensor data page
Browse files Browse the repository at this point in the history
  • Loading branch information
rideam committed Feb 24, 2023
1 parent 5af5fef commit 27f0e3b
Show file tree
Hide file tree
Showing 40 changed files with 535 additions and 377 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# User Platform
# Bima Insurance Platform

Flask app to simulate user platform for payouts

![](./docs/img/cover.png)

## Tech Stack

- `Flask`
- `Algorand`
- `Postgres`


## Setup
Expand All @@ -21,6 +24,8 @@ ACCOUNT1_ADDRESS=
ACCOUNT1_MNEMONIC=
ACCOUNT2_ADDRESS=
ACCOUNT2_MNEMONIC=
ADMIN_USERNAME=
ADMIN_PASSWORD=
```

## Detailed app description
Expand Down
93 changes: 65 additions & 28 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from flask import Flask
from flask import Flask, Response
from flask_migrate import Migrate

import views
Expand All @@ -12,22 +12,73 @@
Farm, \
Role, \
User
from flask_admin import Admin
from flask_admin import Admin, AdminIndexView
from flask_admin.contrib.sqla import ModelView

from flask_httpauth import HTTPBasicAuth
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.exceptions import HTTPException

app = Flask(__name__)
app.secret_key = settings.secret_key
app.config.from_object(settings.configClass)
auth = HTTPBasicAuth()

users = {
settings.admin_user: generate_password_hash(settings.admin_pwd)
}

db.init_app(app)
migrate = Migrate(app, db)

admin = Admin(app, name='Insurance', template_mode='bootstrap4')

@auth.verify_password
def verify_password(username, password):
""" Verify admin username and password for the admin page
"""

if username in users and \
check_password_hash(users.get(username), password):
return username


login_required_view = auth.login_required(lambda: None)


def is_authenticated():
try:
return login_required_view() is None
except HTTPException:
return False


class AuthException(HTTPException):
def __init__(self, message):
super().__init__(message, Response(
"You could not be authenticated.", 401,
{'WWW-Authenticate': 'Basic realm="Login Required"'}))


# class MyModelView(ModelView):
# def is_accessible(self):
# if not is_authenticated():
# raise AuthException('Not authenticated.')
# else:
# return True


class MyAdminIndexView(AdminIndexView):

def is_accessible(self):

if not is_authenticated():
raise AuthException('Not authenticated.')
else:
return True


class PolicyView(ModelView):
column_hide_backrefs = False
# column_list = ("strike_event")
# inline_models = (Event,)
column_list = ('name',
'description',
Expand All @@ -38,16 +89,9 @@ class PolicyView(ModelView):
'strike_event'
)

# def __init__(self, session, **kwargs):
# super(PolicyView, self).__init__(Policy, session, **kwargs)


class EventView(ModelView):
column_hide_backrefs = False
# column_list = ("policy_id")
# inline_models = (Policy,)
# def __init__(self, session, **kwargs):
# super(StrikeEventView, self).__init__(StrikeEvent, session, **kwargs)


class UserView(ModelView):
Expand All @@ -59,35 +103,28 @@ class FarmView(ModelView):
column_hide_backrefs = False


admin.add_view(PolicyView(model=Policy, session=db.session))
admin.add_view(EventView(model=Event, session=db.session))
class RoleView(ModelView):
column_hide_backrefs = True


admin = Admin(app, name='Bima', template_mode=settings.template_mode, index_view=MyAdminIndexView())
admin.add_view(UserView(model=User, session=db.session))
admin.add_view(ModelView(model=Role, session=db.session))
admin.add_view(RoleView(model=Role, session=db.session))
admin.add_view(FarmView(model=Farm, session=db.session))
admin.add_view(PolicyView(model=Policy, session=db.session))
admin.add_view(EventView(model=Event, session=db.session))


@app.shell_context_processor
def make_shell_context():
return dict(db=db, Weather=Weather)


auth.login_manager.init_app(app)
appauth.login_manager.init_app(app)

app.register_blueprint(views.main_bp)
app.register_blueprint(auth.auth_bp)
app.register_blueprint(appauth.auth_bp)
app.register_blueprint(data.data_bp)

# def seed_db():
# # with app.app_context():
# user_role = Role(name='farmer')
# super_user_role = Role(name='admin')
# db.session.add(user_role)
# db.session.add(super_user_role)
# db.session.commit()


if __name__ == "__main__":
# db.create_all()
# with app.app_context():
# seed_db()
app.run(host='0.0.0.0', port=5001, debug=True)
6 changes: 4 additions & 2 deletions config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import os

import settings

basedir = os.path.abspath(os.path.dirname(__file__))


Expand All @@ -11,5 +13,5 @@ class BaseConfig(object):
SQLALCHEMY_DATABASE_URI = 'postgresql:///playground'
# SQLALCHEMY_DATABASE_URI = 'sqlite:///database.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
FLASK_ADMIN_SWATCH = 'lumen'
# FLASK_ADMIN_SWATCH = 'united'
FLASK_ADMIN_SWATCH = 'readable'
TEMPLATE_MODE = settings.template_mode
24 changes: 14 additions & 10 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,31 @@ Upon successful login the account page shows the user their account details

![](img/accountpage.png)

- the user also sees all the policies they have joined
- they are able to pay their premiums for the current month and the transaction will be stored on chain

![](img/mypolicies.png)


# Policy Page

On the Policy page the user can join a policy and the transaction will be stored on the blockchain

![](img/policyenrol.png)
![](img/policysuccess.png)
![](img/policyonchain.png)


# Premium page
# Payouts

On the premium page the user is able to pay their premium
Payouts are auto processed when a strike event attached to the user's policy is triggered

![](img/premiumpage.png)
![](img/premiumsuccess.png)
![](img/premiumonchain.png)
![](img/payoutspage.png)


# Payouts
# Sensor Data

On the sensor data page a user will see the data collected by the sensors on their farm

Still being implemented
- as a graph with the most recent data displayed first
- the user is able to view the data stored on the blockchain for verifiability of the data

![](img/payoutspage.png)
![](img/sensordata.png)
Binary file modified docs/img/accountpage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/cover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/login.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/mypolicies.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/payoutspage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/policyenrol.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/img/policyonchain.png
Binary file not shown.
Binary file removed docs/img/policysuccess.png
Binary file not shown.
Binary file removed docs/img/premiumonchain.png
Binary file not shown.
Binary file removed docs/img/premiumpage.png
Binary file not shown.
Binary file removed docs/img/premiumsuccess.png
Binary file not shown.
Binary file added docs/img/sensordata.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 7 additions & 36 deletions forms.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,13 @@
from algosdk.constants import address_len, note_max_length
from flask_wtf import FlaskForm
from wtforms import DecimalField, StringField, SubmitField
from wtforms.validators import InputRequired, Optional, Length, NumberRange


class EnrolForm(FlaskForm):
"""Policy enrollment form"""
signature = StringField(
'Signature',
validators=[InputRequired(), Length(min=5)],
render_kw={"placeholder": "Signature"}
)
submit = SubmitField('Join')


class PayForm(FlaskForm):
"""Payment form"""
amount = DecimalField(
'Amount',
validators=[InputRequired(), NumberRange(min=0)],
render_kw={"placeholder": "Premium Amount"}
)
receiver = StringField(
'Receiver',
validators=[InputRequired(), Length(min=address_len, max=address_len)],
render_kw={"placeholder": "Receiver Address"}
)
note = StringField(
'Note',
validators=[Optional(), Length(max=note_max_length)],
render_kw={"placeholder": "Note"})
submit = SubmitField('Pay')
from wtforms import StringField, SubmitField
from wtforms.validators import InputRequired


class LoginForm(FlaskForm):
"""Login form"""
passphrase = StringField('25-word Passphrase',
validators=[InputRequired()],
render_kw={"placeholder": "Enter your 25-word Passphrase"}
)
passphrase = StringField(
'25-word Passphrase',
validators=[InputRequired()],
render_kw={"placeholder": "Enter your 25-word Passphrase"}
)
submit = SubmitField('Login')
42 changes: 0 additions & 42 deletions indexer.py

This file was deleted.

15 changes: 15 additions & 0 deletions microcontroller/dth11.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from machine import Pin
import dht


def get_temp_hum():
sensor = dht.DHT11(Pin(5))
try:
sensor.measure()
t = sensor.temperature()
h = sensor.humidity()
print('Temperature: %3.1f C' % t)
print('Humidity: %3.1f %%' % h)
return t, h
except OSError as e:
print('Sensor Reading Failed')
54 changes: 54 additions & 0 deletions microcontroller/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import network
import time
import creds
import urequests
import dht11
import soil_moisture
import ujson


def connect_wifi():
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect(creds.ssid, creds.pwd)

timeout = 6
delay = 0
if not wifi.isconnected():
print('connecting ..')
while not wifi.isconnected() and delay < timeout:
print(timeout - delay)
delay = delay + 1
time.sleep(1)

if wifi.isconnected():
print('Connected')
else:
print('Timed Out')

return wifi


def get_data():
temperature, humidity = dht11.get_temp_hum()
#soil_m = soil_moisture.get_soil_moisture()

post_data = ujson.dumps({'temperature': temperature, 'humidity': humidity, 'soil_moisture': 50 , 'farm': 'Puma Farm', 'crop': 'Maize'})
request_url = creds.endpoint + '/weather'
print(request_url)
try:
res = urequests.post(request_url, headers={'content-type': 'application/json'}, data=post_data)
print(res.json)
except Exception as e:
print(e)


def main():
wifi = connect_wifi()
if wifi.isconnected():
while True:
get_data()
time.sleep(20)


main()
Loading

0 comments on commit 27f0e3b

Please sign in to comment.