diff options
author | CruiseDevice | 2018-10-24 16:58:51 +0530 |
---|---|---|
committer | CruiseDevice | 2018-10-24 16:58:51 +0530 |
commit | 8980733d799444665a671c6f8bd66dc16ed755fe (patch) | |
tree | 13e215a5487996f844182038003698319af75fd4 | |
parent | 113918f3a073e94a4f9b6dce25c30a71658e63b9 (diff) | |
download | sbhs_server-8980733d799444665a671c6f8bd66dc16ed755fe.tar.gz sbhs_server-8980733d799444665a671c6f8bd66dc16ed755fe.tar.bz2 sbhs_server-8980733d799444665a671c6f8bd66dc16ed755fe.zip |
Create experiment, moderator urls and update views
- experiment initiation
- create log_data of experiment
- create graph from 1000 instance of log_data of particular mid
- download user log_files
- download zip of complete experiments directory which contains log_files of all the users
- show all bookings in moderator dashboard
- show all connected boards in moderator dashboard
- test connected board if it is vacant.
- fetch_logs from given time of each user.
- seperate raspi_server from main server.
- specify path for experiment logs and global logs
-rw-r--r-- | sbhs/urls.py | 37 | ||||
-rw-r--r-- | sbhs/views.py | 510 | ||||
-rw-r--r-- | sbhs_raspi/requirements.txt | 6 | ||||
-rw-r--r-- | sbhs_raspi/sbhs.py | 179 | ||||
-rw-r--r-- | sbhs_raspi/sbhs_server.py | 299 | ||||
-rw-r--r-- | sbhs_server/settings.py | 21 |
6 files changed, 493 insertions, 559 deletions
diff --git a/sbhs/urls.py b/sbhs/urls.py index 07ad629..cfba27f 100644 --- a/sbhs/urls.py +++ b/sbhs/urls.py @@ -57,11 +57,42 @@ urlpatterns = [ ################## Experiment urls ##################### url(r'^experiment/check_connection/$',views.check_connection, name='experiment_check_connection'), - - url(r'^experiment/initiate/$',views.initiation,name='experiment_initiate'), - url(r'^experiment/map_machines/$',views.map_sbhs_to_rpi,name='experiment_initiate'), + url(r'^experiment/initiate/$',views.initiation, + name='experiment_initiate'), + url(r'^experiment/client_version/?$', views.client_version, + name='experiment_client_version'), + url(r'^experiment/map_machines/$',views.map_sbhs_to_rpi, + name='experiment_initiate'), + url(r'^experiment/experiment/?$', views.experiment, + name='experiment_experiment'), + url(r'^experiment/logs/$',views.logs,name='experiment_logs'), + url(r'^experiment/logs/([0-9]+)/$',views.download_user_log, + name='experiment_logs'), ################## Moderator urls ##################### url(r'^moderator/$',views.moderator_dashboard, name='moderator_dashboard'), + url(r'^moderator/all-bookings/$',views.all_bookings, + name='all_bookings'), + url(r'^moderator/all-boards/$',views.all_boards, + name='all_boards'), + url(r'^moderator/profile/(?P<mid>\d+)/$',views.profile, + name='profile'), + url(r'^moderator/log/(?P<mid>\d+)/$',views.download_log, + name='download_log'), + url(r'^moderator/logs_folder_index/?$',views.logs_folder_index, + name='logs_folder_index'), + url(r'^moderator/all-images/$',views.all_images,name='all_images'), + url(r'^moderator/test-boards/$',views.test_boards,name='test_boards'), + url(r'^moderator/update-mid/$',views.update_mid,name='update_mid'), + url(r'^moderator/fetch-logs/$',views.fetch_logs,name='fetch_logs'), + url(r'^moderator/fetch-logs/(?P<experiment_id>\d+)/$',views.download_file, + name='download_file'), + + url(r'^moderator/turn-on-all-boards/$',views.turn_on_all_boards, + name='turn_on_all_boards'), + url(r'^moderator/turn-off-all-boards/$',views.turn_off_all_boards, + name='turn_off_all_boards'), + url(r'^moderator/book-all-suser-slots/$',views.book_all_suser_slots, + name='book_all_suser_slots'), ] diff --git a/sbhs/views.py b/sbhs/views.py index 37d307e..1d8c069 100644 --- a/sbhs/views.py +++ b/sbhs/views.py @@ -6,13 +6,13 @@ import random import zipfile import inspect import pytz -# import MySQLdb import datetime import requests -import subprocess +import subprocess, zipfile # import serial from textwrap import dedent from time import gmtime, strftime +import time from datetime import datetime, timedelta, date from django.urls import reverse @@ -20,6 +20,7 @@ from django.conf import settings from django.db import connection from django.utils import timezone from django.db.models import Count +from django.contrib.auth.models import User # import automatic_slot_booking from django.contrib import messages from django.template.loader import render_to_string @@ -30,21 +31,24 @@ from django.shortcuts import render, redirect, get_object_or_404 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from django.http import HttpResponse, HttpResponseRedirect,\ Http404, HttpResponseServerError, JsonResponse -from urllib.parse import urljoin -from .models import Board, Experiment, Profile, Slot#, Webcam -from .forms import UserLoginForm, UserRegistrationForm, SlotCreationForm +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger + + +from .models import Board, Experiment, Profile, Slot, UserBoard#, Webcam +from .forms import ( + UserLoginForm, UserRegistrationForm, SlotCreationForm, FilterLogsForm + ) from .send_emails import send_user_mail from sbhs_server import credentials as credentials from sbhs.decorators import email_verified - ################# pages views ####################### - def index(request, next_url=None): if request.user.is_authenticated(): return render(request,'account/home.html') return render(request,"pages/pages_index.html") + def about(req): return render(req, "pages/about.html") @@ -52,6 +56,7 @@ def about(req): def info(request): return render(request,"pages/info.html") + def downloads(req): return redirect("http://sbhs.os-hardware.in/downloads") @@ -59,19 +64,26 @@ def downloads(req): def theory(req): return render(req, "pages/theory.html") + def procedure(req): return render(req, "pages/procedure.html") + def experiments(req): return render(req, "pages/experiments.html") + def feedback(req): return render(req, "pages/feedback.html") #########Account Views ########### @email_verified def account_index(request): - if request.user.is_authenticated(): + user = request.user + if user.is_authenticated(): + if not UserBoard.objects.filter(user=user).exists(): + random_board = Board.objects.order_by('?').last() + UserBoard.objects.create(user=user, board=random_board) return render(request,'account/home.html') return render(request,'account/account_index.html',{ @@ -215,7 +227,7 @@ def update_email(request): @email_verified def slot_new(request): user = request.user - slot_history = Slot.objects.filter(user=user).order_by("start_time") + slot_history = Slot.objects.filter(user=user).order_by("-start_time") context = {} now = timezone.now() if not request.user.is_authenticated(): @@ -261,47 +273,12 @@ def slot_new(request): ###################Experiment Views ###################### def check_connection(request): - message = {"message":"TESTOK"} - return JsonResponse(message, safe=True, status=200) - -@login_required -def initial_login(request): - """ Logs in an user for conducting the experiment on the specified - board. - Input: req:request object. - Output: HttpResponse object. - """ - - username = request.POST.get("username") - rpi_ip = '' - try: - assigned_mid = 2 - except Exception as e: - return JsonResponse({ - "STATUS":400, - "MESSAGE":{ - "IS_IP":"1", - "DATA":"Invalid username" - } - }) - rpi_ip = '10.102.54.71' - if rpi_ip is None: - return JsonResponse({ - "STATUS":400, - "MESSAGE":{ - "IS_IP":"1", - "DATA":"Board is currently offline" - } - }) - return JsonResponse({ - "STATUS":200, - "MESSAGE":{ - "IS_IP":"1", - "DATA":rpi_ip - } - }) + return HttpResponse("TESTOK") +def client_version(request): + return HttpResponse(str(settings.CLIENT_VERSION)) + @csrf_exempt def initiation(request): username = request.POST.get("username") @@ -310,23 +287,45 @@ def initiation(request): if user: if user.is_active: now = timezone.now() - slots = Slot.objects.filter(user=user, - start_time__gte=now, - end_time__lt = now - ) - + slots = Slot.objects.get_current_slots(user).order_by("id") slot = slots.last() - if slot: - filename = '' + board = UserBoard.objects.get(user=user).board + check_status_path = "reset/{0}".format(board.usb_id) + check_status = connect_sbhs(board.raspi_path, check_status_path) + if check_status["status"] and slot: + filename = datetime.strftime(now, "%Y%b%d_%H_%M_%S.txt") + logdir = os.path.join(settings.EXPERIMENT_LOGS_DIR, + user.username + ) + user_file = user.username + "/" + filename + if not os.path.exists(logdir): + os.makedirs(logdir) + + if not Experiment.objects.filter(slot=slot, + log=user_file + ).exists(): + Experiment.objects.create(slot=slot, + log=user_file + ) + message = { "STATUS":1, - "MESSAGE": filename - } + "MESSAGE": filename, + } + elif check_status["status"] and not slot: + message = { + "STATUS":0, + "MESSAGE":"Slot has ended. Please book the next slot." + } + elif not check_status["status"] and slot: + message = { + "STATUS":0, + "MESSAGE":"Slot is booked but Board is currently offline." + } else: message = { "STATUS":0, - "MESSAGE":"Slot has ended. Please book the next slot \ - to continue the experiment" + "MESSAGE":"Board is currently offline. Contact admin." } else: message = { @@ -339,7 +338,6 @@ def initiation(request): "STATUS":0, "MESSAGE":"Invalid username and password" } - return JsonResponse(message, safe=True, status=200) def map_sbhs_to_rpi(client_ip): @@ -351,8 +349,7 @@ def map_sbhs_to_rpi(client_ip): for r_pi in r_pis: rpi_map = {} rpi_map["rpi_ip"] = r_pi - rpi_connect = connect_sbhs(r_pi, "get_machine_ids") - mac_ids = json.loads(rpi_connect) + mac_ids = connect_sbhs(r_pi, "get_machine_ids") board = Board() board.save_board_details(r_pi, mac_ids) rpi_map["mac_ids"] = [i['sbhs_mac_id'] for i in mac_ids] @@ -361,17 +358,179 @@ def map_sbhs_to_rpi(client_ip): rpi_map = {} client_name = client_ip + ":1234" rpi_map["rpi_ip"] = client_name - rpi_connect = connect_sbhs(client_name, "get_machine_ids") - mac_ids = json.loads(rpi_connect) + mac_ids = connect_sbhs(client_name, "get_machine_ids") board = Board() board.save_board_details(client_name, mac_ids) + rpi_map["mac_ids"] = [i['sbhs_mac_id'] for i in mac_ids] + map_machines.append(rpi_map) + return map_machines def connect_sbhs(rpi_ip, experiment_url): connect_rpi = requests.get("http://{0}/experiment/{1}".format( rpi_ip, experiment_url ) ) - return connect_rpi.text + data = json.loads(connect_rpi.text) + return data + +@csrf_exempt +def experiment(request): + try: + username = request.POST.get("username") + server_start_ts = int(time.time() * 1000) + user = User.objects.get(username=username) + slot = Slot.objects.get_current_slots(user)\ + .order_by("start_time").last() + board = UserBoard.objects.get(user=user).board + experiment = Experiment.objects.filter(slot=slot) + if experiment.exists(): + experiment = experiment.first() + now = timezone.now() + endtime = slot.end_time + if endtime > now: + timeleft = int((endtime-now).seconds) + heat = max(min(int(request.POST.get("heat")), 100), 0) + fan = max(min(int(request.POST.get("fan")), 100), 0) + set_heat_url = "set_heat/{0}/{1}".format(board.usb_id, heat) + set_fan_url = "set_fan/{0}/{1}".format(board.usb_id, fan) + get_temp_url = "get_temp/{0}".format(board.usb_id) + set_heat = connect_sbhs(board.raspi_path, set_heat_url) + set_fan = connect_sbhs(board.raspi_path, set_fan_url) + get_temp = connect_sbhs(board.raspi_path,get_temp_url) + temp = get_temp["temp"] + log_data(board.mid, heat, fan, temp) + + server_end_ts = int(time.time() * 1000) + + STATUS = 1 + MESSAGE = "%s %d %d %2.2f" % (request.POST.get("iteration"), + heat, + fan, + temp) + MESSAGE = "%s %s %d %d,%s,%d" % (MESSAGE, + request.POST.get("timestamp"), + server_start_ts, + server_end_ts, + request.POST.get("variables"), + timeleft) + experiment_log_path = os.path.join( + settings.EXPERIMENT_LOGS_DIR, + experiment.log + ) + f = open(experiment_log_path, "a") + f.write(" ".join(MESSAGE.split(",")[:2]) + "\n") + f.close() + # Experiment.objects.create(slot=slot, log=experiment_log_path) + else: + STATUS = 0 + MESSAGE = "Slot has ended. Please book the next slot to \ + continue the experiment." + else: + STATUS = 0 + MESSAGE = "You haven't booked this slot." + + return HttpResponse(json.dumps({"STATUS": STATUS, "MESSAGE": MESSAGE})) + except Exception as e: + raise Exception + return HttpResponse(json.dumps({"STATUS": 0, + "MESSAGE": "Please Contact Admin" + } + ) + ) + +def log_data(mid, heat, fan, temp): + + data = "{0} {1} {2} {3}\n".format(int(time.time()),str(heat), + str(fan), str(temp) + ) + global_logfile = settings.SBHS_GLOBAL_LOG_DIR + "/" + str(mid) + ".log" + try: + with open(global_logfile, "a") as global_loghandler: + global_loghandler.write(data) + return True + except: + return False + +@login_required +def logs(request): + user = request.user + context = {} + all_bookings = Slot.objects.filter(user__username=user) + all_booking_ids = [booking.id for booking in all_bookings] + experiment = Experiment.objects.select_related("slot").filter(slot_id__in=all_booking_ids) + for exp in experiment: + exp.logname = exp.log.split("/")[-1] + context['exp.logname'] = exp.logname + context['experiment'] = experiment + return render(request,'experiment/logs.html',context) + +@login_required +def download_user_log(request, experiment_id): + user = request.user + experiment_data = Experiment.objects.get(slot__id=experiment_id) + f = open(os.path.join(settings.EXPERIMENT_LOGS_DIR, experiment_data.log),"r") + data = f.read() + print(data) + f.close() + return HttpResponse(data, content_type="text/text") + + +# @csrf_exempt +# def reset(req): +# try: +# from pi_server.settings import boards +# user = req.user +# if user.is_authenticated(): +# key = str(user.board.mid) +# experiment = Experiment.objects.select_related().filter(id=boards[key]["experiment_id"]) + +# if len(experiment) == 1 and user == experiment[0].booking.account: +# experiment = experiment[0] +# now = datetime.datetime.now() +# endtime = experiment.booking.end_time() + +# boards[key]["board"].setHeat(0) +# boards[key]["board"].setFan(100) + +# log_data(boards[key]["board"], key, experiment.id, 0, 100) +# if endtime < now: +# boards[key]["experiment_id"] = None +# except: +# pass + +# return HttpResponse("") + +# def log_data(sbhs, mid, experiment_id, heat=None, fan=None, temp=None): +# if heat is None: +# heat = sbhs.getHeat() +# if fan is None: +# fan = sbhs.getFan() +# if temp is None: +# temp = sbhs.getTemp() + +# data = "%d %s %s %s\n" % (int(time.time()), str(heat), str(fan), str(temp)) +# global_logfile = settings.SBHS_GLOBAL_LOG_DIR + "/" + str(mid) + ".log" +# with open(global_logfile, "a") as global_loghandler: +# global_loghandler.write(data) + +# def validate_log_file(req): +# import hashlib +# data = req.POST.get("data") +# data = data.strip().split("\n") +# clean_data = "" +# for line in data: +# columns = line.split(" ") +# if len(columns) >= 6: +# clean_data += (" ".join(columns[0:6]) + "\n") + +# checksum = hashlib.sha1(clean_data).hexdigest() + +# try: +# e = Experiment.objects.get(checksum=checksum) +# return HttpResponse("TRUE") +# except: +# return HttpResponse("FALSE") + ################## Moderator Views ########################## @@ -387,9 +546,224 @@ def moderator_dashboard(request): if not is_moderator(user): raise Http404("You are not allowed to see this page!") else: - all_boards = map_sbhs_to_rpi(request.META["SERVER_NAME"]) - context["all_active_boards"] = all_boards - return render(request, 'dashboard/dashboard_index.html', context) + board_check = map_sbhs_to_rpi(request.META["SERVER_NAME"]) + board = Board() + all_mac_ids = [] + for machines in board_check: + all_mac_ids.extend(machines["mac_ids"]) + board.switch_off_inactive_boards(all_mac_ids) + context["all_boards"] = Board.objects.all() + return render(request, 'dashboard/show_all_boards.html', context) + +@login_required +def profile(request, mid): + user = request.user + context = {} + if not is_moderator(user): + raise Http404("You are not allowed to see this page.") + else: + try: + filename = settings.SBHS_GLOBAL_LOG_DIR + "/" + str(mid) + ".log" + print(filename) + except: + raise Http404("Log does not exist for this profile.") + + delta_T = 1000 + data = subprocess.check_output("tail -n {0} {1}".format( + delta_T, filename + ), + shell=True) + data = data.split("\n".encode()) + + heatcsv = "" + fancsv = "" + tempcsv = "" + + plot = [] + for t in range(len(data)): + line = data[t].decode("utf-8") + entry = line.strip().split(" ") + try: + plot.append([int(float(i)) for i in entry[0:-1] \ + + [float(entry[-1])]]) + heatcsv += "{0},{1}".format(t+1, entry[1]) + fancsv += "{0},{1}".format(t+1,entry[2]) + tempcsv += "{0},{1}".format(t+1, entry[3]) + except: + continue + + plot = zip(*plot) + context["mid"] = mid + context["delta_T"] = delta_T + context["heat"] = heatcsv + context["fan"] = fancsv + context["temp"] = tempcsv + + return render(request,"dashboard/profile.html",context) + +@login_required +def download_log(request, mid): + user = request.user + if not is_moderator(user): + raise Http404("You are not allowed to see this page.") + else: + try: + global_logfile = settings.SBHS_GLOBAL_LOG_DIR + "/" + str(mid) \ + + ".log" + f = open(global_logfile,'r') + data = f.read() + f.close() + return HttpResponse(data, content_type='text/text') + except: + return HttpResponse("Requested log file does not exist") + +def zipdir(path,ziph): + for root, dirs, files in os.walk(path): + for file in files: + ziph.write(os.path.join(root,file)) + +@login_required +def logs_folder_index(request): + user = request.user + if not is_moderator(user): + raise Http404("You are not allowed to see this page.") + else: + if os.path.exists('Experiments.zip'): + os.remove('Experiments.zip') + + with zipfile.ZipFile('Experiments.zip','w',zipfile.ZIP_DEFLATED) as zipf: + path = settings.BASE_DIR + '/experiments/' + zipdir(path,zipf) + + with open('Experiments.zip','rb') as stream: + response = HttpResponse(stream, + content_type='application/force-download') + response['Content-Disposition'] = 'attachment; filename="{0}"'\ + .format('Experiments.zip') + return response + +@login_required +def all_bookings(request): + user = request.user + context = {} + if not is_moderator(user): + raise Http404("You are not allowed to see this page.") + else: + all_bookings = Slot.objects.all().order_by("-start_time") + paginator = Paginator(all_bookings, 20) + page = request.GET.get('page') + try: + slots = paginator.page(page) + except PageNotAnInteger: + slots = paginator.page(1) + except EmptyPage: + slots = paginator.page(paginator.num_pages) + context["slots"] = slots + return render(request,'dashboard/all_bookings.html', context) + + + +@login_required +def all_boards(request): + user = request.user + if not is_moderator(user): + raise Http404("You are not allowed to see this page.") + else: + return render(request,'dashboard/all_boards.html') + + +@login_required +def all_images(request): + user = request.user + if not is_moderator(user): + raise Http404("You are not allowed to see this page.") + else: + return render(request,'dashboard/all_images.html') + +@login_required +def test_boards(request): + user = request.user + now = timezone.now() + context = {} + if not is_moderator(user): + raise Http404("You are not allowed to see this page.") + else: + boards = Board.objects.filter(online=True) + slot_history = Slot.objects.all().order_by("-start_time") + context["boards"] = boards + context["slot_history"] = slot_history[0] + context["now"] = now + return render(request,'dashboard/test_boards.html',context) + +@login_required +def update_mid(request): + user = request.user + if not is_moderator(user): + raise Http404("You are not allowed to see this page.") + else: + return render(request,'dashboard/update_mid.html') + +@login_required +def fetch_logs(request): + user = request.user + context = {} + now = datetime.now() + if not is_moderator(user): + raise Http404("You are not allowed to see this page.") + else: + if request.method == 'POST': + form = FilterLogsForm(request.POST) + if form.is_valid(): + start_date = form.data["start_time"] + end_date = form.data["end_time"] + if start_date and end_date: + ys,ms,ds = [int(x) for x in start_date.split('-')] + ye,me,de =[int(x) for x in end_date.split('-')] + slot = Slot.objects.filter( + start_time__date__gte=date(ys,ms,ds), + end_time__date__lte=date(ye,me,de) + ) + experiment = Experiment.objects.filter(slot__in=slot) + context["experiments"] = experiment + else: + form=FilterLogsForm() + context['form']=form + return render(request,'dashboard/fetch_logs.html',context) + +def download_file(request, experiment_id): + experiment = Experiment.objects.get(id=experiment_id) + response = HttpResponse(content_type='application/text') + response['Content-Disposition'] = 'attachment; filename={0}'.format( + experiment.log + ) + response.write(open("{0}/{1}".format(settings.MEDIA_ROOT, + experiment.log) + ).read()) + return response + +@login_required +def turn_on_all_boards(request): + user = request.user + if not is_moderator(user): + raise Http404("You are not allowed to see this page.") + else: + return HttpResponseRedirect(reverse('moderator_dashboard')) + +@login_required +def turn_off_all_boards(request): + user = request.user + if not is_moderator(user): + raise Http404("You are not allowed to see this page.") + else: + return HttpResponseRedirect(reverse('moderator_dashboard')) + +@login_required +def book_all_suser_slots(request): + user = request.user + if not is_moderator(user): + raise Http404("You are not allowed to see this page.") + else: + return HttpResponseRedirect(reverse('moderator_dashboard')) # @login_required diff --git a/sbhs_raspi/requirements.txt b/sbhs_raspi/requirements.txt deleted file mode 100644 index 5f73360..0000000 --- a/sbhs_raspi/requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Please run sbhs_communication_server files i.e. sbhs_server.py and sbhs.py in python 2 only. -# This is because we could not figure out the working of pyserial with python 3. - -flask==1.0.2 -pyserial==3.4 - diff --git a/sbhs_raspi/sbhs.py b/sbhs_raspi/sbhs.py deleted file mode 100644 index 2f0c200..0000000 --- a/sbhs_raspi/sbhs.py +++ /dev/null @@ -1,179 +0,0 @@ -import serial -import os -import logging -from time import localtime, strftime, sleep - - -logging.basicConfig(filename="sbhserr.log", - format='%(asctime)s --- %(message)s' - ) -logger=logging.getLogger() -logger.setLevel(logging.DEBUG) - -class SbhsServer(object): - """ This is the Single Board Heater System class """ - - def get_usb_devices(self): - usb_ids = [] - for tty in os.listdir('/dev'): - if tty.startswith('ttyUSB'): - try: - usb_ids.append(int(tty[6:])) - except ValueError: - logger.error("Could not get {0}".format(tty)) - return usb_ids - - def map_sbhs_to_usb(self, usb_devices): - sbhs_map = [] - if usb_devices: - for usb_id in usb_devices: - sbhs = Sbhs(dev_id=usb_id) - status = sbhs.connect_device() - if status: - board = sbhs.get_machine_id() - logger.info("USB {0} is connected to SBHS machine id {1}" - .format(usb_id, board) - ) - sbhs_map.append({"usb_id": usb_id, "sbhs_mac_id": board}) - return sbhs_map - - -class Sbhs(object): - - def __init__(self, dev_id): - - self.outgoing_machine_id = 252 - self.incoming_fan = 253 - self.incoming_heat = 254 - self.outgoing_temp = 255 - self.max_heat = 100 - self.max_fan = 100 - self.dev_id = dev_id - - def connect_device(self): - """ - Open a serial connection via USB to the SBHS using USB Device Number - """ - # check for valid device number - - usb_device_file = '/dev/ttyUSB{}'.format(self.dev_id) - try: - self.boardcon = serial.Serial(port=usb_device_file, - baudrate=9600, bytesize=8, - parity='N', stopbits=1, - timeout=2 - ) - # org stopbits = 1 - status = True - except Exception as e: - status = False - logger.error("Serial connection with {0} failed" - .format(usb_device_file) - ) - return status - - def get_machine_id(self): - """ Gets machine id from the device """ - try: - self.boardcon.flushInput() - self._write(chr(self.outgoing_machine_id)) - sleep(0.5) - machine_id = ord(self._read(1)) - self.machine_id = machine_id - except Exception as e: - machine_id = -1 - return int(machine_id) - - def set_machine_heat(self, val): - """ Sets the heat, checks if value is valid i.e. within range. - Input: self object, val - Output: Error message if heat cannot be set. - """ - if val > self.max_heat or val < 0: - logger.error("Machine ID {0} tried setting heat {1}%".format()) - return False - - try: - self._write(chr(self.incoming_heat)) - sleep(0.5) - self._write(chr(val)) - return True - except: - print("Error: cannot set heat for machine \ - id {}".format(self.machine_id)) - self.log('cannot set heat for machine id \ - %d' % self.machine_id, 'ERROR') - return False - - def set_machine_fan(self, val): - """ Sets the fan speed, checks if value is valid i.e. within range. - Input: self object, val - Output: Error message if fan cannot be set. - """ - if val > self.max_fan or val < 0: - return False - try: - self._write(chr(self.incoming_fan)) - sleep(0.5) - self._write(chr(val)) - return True - except: - return True - - def get_machine_temp(self): - """ Gets the temperature from the machine. - """ - try: - self.boardcon.flushInput() - self._write(chr(self.outgoing_temp)) - temp = ord(self._read(1)) + (0.1 * ord(self._read(1))) - return temp - except: - print("Error: cannot read temperature from machine id \ - {}".format(self.machine_id)) - self.log('cannot read temperature from machine id %d' \ - % self.machine_id, 'ERROR') - return 0.0 - - def disconnect(self): - """ Reset the board fan and heat values and close the USB connection """ - try: - self.boardcon.close() - self.boardcon = False - self.status = 0 - return True - except: - print('Error: cannot close connection to the machine') - self.log('cannot close connection to the machine', 'ERROR') - return False - - def reset_board(self): - return self.set_machine_heat(0) and self.set_machine_fan(100) - - def _read(self, size): - try: - data = self.boardcon.read(size) - return data - except Exception as e: - raise - - def _write(self, data): - try: - self.boardcon.write(data) - return True - except Exception as e: - raise - - def log(self, msg, level): - try: - errfile = open(LOG_FILE, 'a') # open error log file in append mode - if not errfile: - return - log_msg = '%s %s %s\n' %(level, strftime('%d:%m:%Y %H:%M:%S', \ - localtime()), msg) - - errfile.write(log_msg) - errfile.close() - return - except: - return diff --git a/sbhs_raspi/sbhs_server.py b/sbhs_raspi/sbhs_server.py deleted file mode 100644 index 109c18d..0000000 --- a/sbhs_raspi/sbhs_server.py +++ /dev/null @@ -1,299 +0,0 @@ -from flask import (Flask, flash, redirect, render_template, request, url_for, - Response, jsonify) -from logging.config import dictConfig -from sbhs import SbhsServer, Sbhs - -# dictConfig({ -# 'version': 1, -# 'formatters': {'default': { -# 'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s', -# }}, -# 'handlers': {'file': { -# 'class': 'logging.FileHandler', -# 'formatter': 'default', -# 'filename': 'error.log', -# }}, - -# 'root': { -# 'level': 'DEBUG', -# 'handlers': ['file'] -# } -# }) - -app = Flask(__name__) - -@app.route('/experiment/check_connection') -def check_connection(): - return Response("TESTOK") - -@app.route('/experiment/client_version') -def client_version(): - return Response("3") - -@app.route('/experiment/get_machine_ids') -def get_machine_ids(): - sbhs_server = SbhsServer() - all_mac_ids = sbhs_server.map_sbhs_to_usb(sbhs_server.get_usb_devices()) - return jsonify(all_mac_ids) - -@app.route('/experiment/set_fan/<int:dev_num>/<int:fan_speed>') -def set_fan(dev_num, fan_speed): - sbhs_server = Sbhs(dev_num) - connect = sbhs_server.connect_device() - message = "Could not set fan speed" - if connect: - status = sbhs_server.set_machine_fan(fan_speed) - if status: - message = "Set fan speed at {}%".format(fan_speed) - return Response(message) - -@app.route('/experiment/set_heat/<int:dev_num>/<int:heat>') -def set_heat(dev_num, heat): - sbhs_server = Sbhs(dev_num) - connect = sbhs_server.connect_device() - message = "Could not set heat" - if connect: - status = sbhs_server.set_machine_heat(heat) - if status: - message = "Set heat at {}%".format(heat) - return Response(message) - -@app.route('/experiment/get_temp/<int:dev_num>') -def get_temp(dev_num): - sbhs_server = Sbhs(dev_num) - connect = sbhs_server.connect_device() - message = "Could not fetch temperature" - if connect: - status = sbhs_server.get_machine_temp() - return jsonify({"temp": status}) - return Response(message) - -@app.route('/experiment/reset/<int:dev_num>') -def reset(dev_num): - sbhs_server = Sbhs(dev_num) - connect = sbhs_server.connect_device() - message = "Reset Failed" - if connect: - status = sbhs_server.reset_board() - message = "Reset Successful" - return Response(message) - -@app.route('/experiment/disconnect/<int:dev_num>') -def disconnect(dev_num): - sbhs_server = Sbhs(dev_num) - connect = sbhs_server.connect_device() - message = "Disconnect Failed" - if connect: - status = sbhs_server.disconnect_machine() - message = "Diconnected" - return Response(message) - -# @app.route('/experiment/shutdown/<int:dev_num>') -# def shutdown(dev_num): -# sbhs_server = SbhsServer() -# connect = sbhs_server.connect_device(dev_num) -# message = "Disconnect Failed" -# if connect: -# status = sbhs_server.shutdown_machine() -# message = "Killed" -# return Response(message) - - -# @csrf_exempt -# def initiation(req): -# username = req.POST.get("username") -# password = req.POST.get("password") -# user = authenticate(username=username, password=password) -# if user is not None: -# if user.is_active: -# user1 = Account.objects.select_related().filter(id=user.id) -# user1 = user1[0] -# user_board = user1.board - -# #allows admin to access the temporary offline devices but prohibits the users to do so -# if user_board.online and (not user_board.temp_offline \ -# or user1.is_admin): -# slots = Slot.slots_now() -# slot_ids = [s.id for s in slots] -# now = datetime.datetime.now() -# bookings = user.booking_set.filter(booking_date__year=now.year, -# booking_date__month=now.month, -# booking_date__day=now.day, -# slot_id__in=slot_ids)\ -# .select_related("slot") -# try: -# cur_booking = bookings[0] -# active_slot = cur_booking.slot -# except: -# cur_booking = None -# active_slot = None - -# if active_slot is not None: -# endtime = cur_booking.end_time() -# if now < endtime: -# filename = datetime.datetime.strftime(now, \ -# "%Y%b%d_%H_%M_%S.txt") -# logdir = os.path.join(settings.EXPERIMENT_LOGS_DIR, \ -# user.username) -# if not os.path.exists(logdir): -# os.makedirs(logdir) - -# f = open(os.path.join(logdir, filename), "a") -# f.close() - -# LOGIN(req, user) - -# e = Experiment() -# e.booking=cur_booking -# e.log=user.username + "/" + filename -# e.save() - -# key = str(user_board.mid) - -# settings.boards[key]["experiment_id"] = e.id - -# reset(req) - -# STATUS = 1 -# MESSAGE = filename -# else: -# reset(req) -# STATUS = 0 -# MESSAGE = "Slot has ended. Please book the next slot \ -# to continue the experiment." -# else: -# STATUS = 0 -# MESSAGE = "You haven't booked this slot." -# else: -# STATUS = 0 -# MESSAGE = "Your SBHS is offline. Please contact the Vlabs \ -# team." -# else: -# STATUS = 0 -# MESSAGE = "Your account is not activated yet. Please check your \ -# email for activation link." -# else: -# STATUS = 0 -# MESSAGE = "Invalid username or password" - -# return HttpResponse(json.dumps({"STATUS": STATUS, "MESSAGE": MESSAGE})) - -# @login_required(redirect_field_name=None) -# @csrf_exempt -# def experiment(req): -# try: -# server_start_ts = int(time.time() * 1000) -# from pi_server.settings import boards -# user = req.user -# key = str(user.board.mid) -# experiment = Experiment.objects.select_related()\ -# .filter(id=boards[key]["experiment_id"]) - -# if len(experiment) == 1 and user.id == experiment[0].booking.account.id and experiment[0].booking.trashed_at == None: -# experiment = experiment[0] -# now = datetime.datetime.now() -# endtime = experiment.booking.end_time() -# if endtime > now: -# timeleft = int((endtime-now).seconds) -# heat = max(min(int(req.POST.get("heat")), 100), 0) -# fan = max(min(int(req.POST.get("fan")), 100), 0) - -# boards[key]["board"].setHeat(heat) -# boards[key]["board"].setFan(fan) -# temperature = boards[key]["board"].getTemp() -# log_data(boards[key]["board"], key, experiment.id, heat=heat, fan=fan, temp=temperature) - -# server_end_ts = int(time.time() * 1000) - -# STATUS = 1 -# MESSAGE = "%s %d %d %2.2f" % (req.POST.get("iteration"), -# heat, -# fan, -# temperature) -# MESSAGE = "%s %s %d %d,%s,%d" % (MESSAGE, -# req.POST.get("timestamp"), -# server_start_ts, -# server_end_ts, -# req.POST.get("variables"), timeleft) - -# f = open(os.path.join(settings.EXPERIMENT_LOGS_DIR, experiment.log), "a") -# f.write(" ".join(MESSAGE.split(",")[:2]) + "\n") -# f.close() -# else: -# # boards[key]["board"].setHeat(0) -# # boards[key]["board"].setFan(100) -# # log_data(boards[key]["board"], key) -# reset(req) - -# STATUS = 0 -# MESSAGE = "Slot has ended. Please book the next slot to continue the experiment." - -# reset(req) -# boards[key]["experiment_id"] = None -# else: -# STATUS = 0 -# MESSAGE = "You haven't booked this slot." - -# return HttpResponse(json.dumps({"STATUS": STATUS, "MESSAGE": MESSAGE})) -# except Exception: -# return HttpResponse(json.dumps({"STATUS": 0, "MESSAGE": "Invalid input. Perhaps the slot has ended. Please book the next slot to continue the experiment."})) - -# @csrf_exempt -# def reset(req): -# try: -# from pi_server.settings import boards -# user = req.user -# if user.is_authenticated(): -# key = str(user.board.mid) -# experiment = Experiment.objects.select_related().filter(id=boards[key]["experiment_id"]) - -# if len(experiment) == 1 and user == experiment[0].booking.account: -# experiment = experiment[0] -# now = datetime.datetime.now() -# endtime = experiment.booking.end_time() - -# boards[key]["board"].setHeat(0) -# boards[key]["board"].setFan(100) - -# log_data(boards[key]["board"], key, experiment.id, 0, 100) -# if endtime < now: -# boards[key]["experiment_id"] = None -# except: -# pass - -# return HttpResponse("") - -# def log_data(sbhs, mid, experiment_id, heat=None, fan=None, temp=None): -# if heat is None: -# heat = sbhs.getHeat() -# if fan is None: -# fan = sbhs.getFan() -# if temp is None: -# temp = sbhs.getTemp() - -# data = "%d %s %s %s\n" % (int(time.time()), str(heat), str(fan), str(temp)) -# global_logfile = settings.SBHS_GLOBAL_LOG_DIR + "/" + str(mid) + ".log" -# with open(global_logfile, "a") as global_loghandler: -# global_loghandler.write(data) - -# def validate_log_file(req): -# import hashlib -# data = req.POST.get("data") -# data = data.strip().split("\n") -# clean_data = "" -# for line in data: -# columns = line.split(" ") -# if len(columns) >= 6: -# clean_data += (" ".join(columns[0:6]) + "\n") - -# checksum = hashlib.sha1(clean_data).hexdigest() - -# try: -# e = Experiment.objects.get(checksum=checksum) -# return HttpResponse("TRUE") -# except: -# return HttpResponse("FALSE") - - -if __name__ == "__main__": - app.run(host="127.0.0.1", port=1234)
\ No newline at end of file diff --git a/sbhs_server/settings.py b/sbhs_server/settings.py index 3b2a68d..b0930fa 100644 --- a/sbhs_server/settings.py +++ b/sbhs_server/settings.py @@ -130,7 +130,7 @@ STATIC_URL = '/static/' SLOT_DURATION = 55 MEDIA_URL = '/media/' -MEDIA_ROOT = os.path.join(BASE_DIR, 'media/') +MEDIA_ROOT = os.path.join(BASE_DIR, 'experiments/') EMAIL_USE_TLS = True @@ -172,7 +172,20 @@ IS_DEVELOPMENT=False DEFAULT_FROM_EMAIL = EMAIL_HOST_USER -RASP_PI_IP = [] -# enter comma separated raspberry pi IPs here +RASP_PI_IPS = [] +# RASP_PI_IPS = ['10.101.202.74:1234'] +# enter comma separated raspberry pi IPs here with ports +# for e.g 127.0.0.1:1234 -RASPI_SBHS_CONNECTION = True if RASP_PI_IP else False +CLIENT_VERSION = 3 +#Client version supported by Django server + +EXPERIMENT_LOGS_DIR = os.path.join(BASE_DIR, 'experiments') +#Path for user experiment folders on Django server. + +SBHS_GLOBAL_LOG_DIR = os.path.join(BASE_DIR, 'log') +# Path for sbhs global log directory on Django server. + +SESSION_EXPIRE_AT_BROWSER_CLOSE = True +CSRF_COOKIE_NAME = "pfesgbxra" +SESSION_COOKIE_NAME = "frffvbaVq" |