diff --git a/agriculture/Procfile b/agriculture/Procfile
deleted file mode 100644
index e342204..0000000
--- a/agriculture/Procfile
+++ /dev/null
@@ -1,2 +0,0 @@
-web: gunicorn --bind :8000 --workers 3 --threads 2 agriculturecommon.wsgi:application
-websocket: daphne -b :: -p 5000 agriculturecommon.asgi:application
diff --git a/agriculture/agriculturecommon/settings.py b/agriculture/agriculturecommon/settings.py
index a66b108..95dc2bc 100644
--- a/agriculture/agriculturecommon/settings.py
+++ b/agriculture/agriculturecommon/settings.py
@@ -39,7 +39,7 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
-ALLOWED_HOSTS = ['127.0.0.1', 'agriculturedemodigi-env-1.us-west-2.elasticbeanstalk.com', 'django-env5.us-west-2.elasticbeanstalk.com', '172.31.27.57', '172.31.18.186']
+ALLOWED_HOSTS = ['*']
# Application definition
diff --git a/agriculture/agriculturecommon/urls.py b/agriculture/agriculturecommon/urls.py
index 559965a..204d18e 100644
--- a/agriculture/agriculturecommon/urls.py
+++ b/agriculture/agriculturecommon/urls.py
@@ -32,8 +32,6 @@
urlpatterns = [
- # path("index.html", include("app.urls")),
-
path("access/", include("login.urls")),
path("", include("agriculturecore.urls")),
diff --git a/agriculture/agriculturecore/drm_requests.py b/agriculture/agriculturecore/drm_requests.py
index bc0d69a..80896e1 100644
--- a/agriculture/agriculturecore/drm_requests.py
+++ b/agriculture/agriculturecore/drm_requests.py
@@ -67,6 +67,7 @@
ID_MOISTURE = "moisture"
ID_CONTROLLERS = "controllers"
+ID_ERROR = "error"
ID_STATIONS = "stations"
ID_WEATHER = "weather"
ID_TANK = "tank"
@@ -148,6 +149,39 @@ def get_device_cloud_session(session):
base_url=user_serialized.server)
+def check_ajax_request(request):
+ """
+ Checks whether the given AJAX request is valid and the user is
+ authenticated.
+ Args:
+ request (:class:`.WSGIRequest`): The HTTP request.
+ Returns:
+ `None` if the request is valid, or a `JsonResponse` with the error
+ if it is not.
+ """
+ if is_authenticated(request):
+ if not request.is_ajax or request.method != "POST":
+ return JsonResponse({ID_ERROR: "AJAX request must be sent using POST"}, status=400)
+ return None
+ else:
+ return JsonResponse({ID_ERROR: "Not authenticated"}, status=401)
+
+
+def get_exception_response(e):
+ """
+ Returns the JSON response with the error contained in the given exception.
+
+ Args:
+ e (:class:`.Exception`): The exception.
+
+ Returns:
+ A JSON response with the details of the exception.
+ """
+ return JsonResponse({ID_ERROR: ("Error in the DRM request: {}.".format(e.response.text)
+ if isinstance(e, DeviceCloudHttpException) else str(e))},
+ status=400)
+
+
def send_device_request(request, target):
"""
Sends a Device Request to DRM to the device with the given ID.
@@ -159,13 +193,12 @@ def send_device_request(request, target):
Returns:
A JSON with the response or the error.
"""
- if not request.is_ajax or request.method != "POST":
- return JsonResponse({"error": "AJAX request must be sent using POST"},
- status=400)
+ # Check if the AJAX request is valid.
+ error = check_ajax_request(request)
+ if error is not None:
+ return error
dc = get_device_cloud(request)
- if dc is None:
- return JsonResponse({"error": "Invalid credentials."}, status=400)
device_id = request.POST[views.PARAM_CONTROLLER_ID]
data = request.POST[PARAM_DATA] if PARAM_DATA in request.POST else None
@@ -176,9 +209,7 @@ def send_device_request(request, target):
return JsonResponse({"data": resp}, status=200)
return JsonResponse({"valid": True}, status=200)
except DeviceCloudHttpException as e:
- return JsonResponse(
- {"error": "Error in the DRM request: {}.".format(e.response.text)},
- status=e.response.status_code)
+ return get_exception_response(e)
def send_request(dc, device_id, target, data=None):
@@ -534,13 +565,12 @@ def get_data_points(request, stream_name):
Returns:
A JSON with the data points or the error.
"""
- if not request.is_ajax or request.method != "POST":
- return JsonResponse({"error": "AJAX request must be sent using POST"},
- status=400)
+ # Check if the AJAX request is valid.
+ error = check_ajax_request(request)
+ if error is not None:
+ return error
dc = get_device_cloud(request)
- if dc is None:
- return JsonResponse({"error": "Invalid credentials."}, status=400)
device_id = request.POST[views.PARAM_CONTROLLER_ID]
interval = int(
diff --git a/agriculture/agriculturecore/templates/index.html b/agriculture/agriculturecore/templates/index.html
deleted file mode 100644
index 9325721..0000000
--- a/agriculture/agriculturecore/templates/index.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
- Title
-
-
-
-
-
\ No newline at end of file
diff --git a/agriculture/agriculturecore/templates/sidebar.html b/agriculture/agriculturecore/templates/sidebar.html
index e03222f..3303ac0 100644
--- a/agriculture/agriculturecore/templates/sidebar.html
+++ b/agriculture/agriculturecore/templates/sidebar.html
@@ -243,7 +243,9 @@
if (data["redirect"])
window.location.replace(data["redirect"]);
}
- );
+ ).fail(function(response) {
+ processErrorResponse(response);
+ });
}
{% endblock %}
\ No newline at end of file
diff --git a/agriculture/agriculturecore/views.py b/agriculture/agriculturecore/views.py
index 4031171..ccb4df5 100644
--- a/agriculture/agriculturecore/views.py
+++ b/agriculture/agriculturecore/views.py
@@ -19,7 +19,6 @@
PARAM_CONTROLLER_ID = "controller_id"
PARAM_FARM_NAME = "farm_name"
-ID_ERROR = "error"
ID_ERROR_TITLE = "error_title"
ID_ERROR_MSG = "error_msg"
ID_ERROR_GUIDE = "error_guide"
@@ -253,13 +252,10 @@ def get_smart_farms(request):
:class:`.JsonResponse`: A JSON response with the list of the Smart
Farms within the DRM account.
"""
- if is_authenticated(request):
- if not request.is_ajax or request.method != "POST":
- return JsonResponse(
- {"error": "AJAX request must be sent using POST"},
- status=400)
- else:
- return redirect('/access/login')
+ # Check if the AJAX request is valid.
+ error = check_ajax_request(request)
+ if error is not None:
+ return error
smart_farms = get_farms(request)
if len(smart_farms) > 0:
@@ -287,13 +283,10 @@ def get_irrigation_stations(request):
Stations corresponding to the controller with the ID provided in
the request.
"""
- if is_authenticated(request):
- if not request.is_ajax or request.method != "POST":
- return JsonResponse(
- {"error": "AJAX request must be sent using POST"},
- status=400)
- else:
- return redirect('/access/login')
+ # Check if the AJAX request is valid.
+ error = check_ajax_request(request)
+ if error is not None:
+ return error
# Get the controller ID from the POST request.
controller_id = request.POST[PARAM_CONTROLLER_ID]
@@ -308,7 +301,7 @@ def get_irrigation_stations(request):
ID_ERROR_MSG: NO_STATIONS_MSG,
ID_ERROR_GUIDE: SETUP_MODULES_GUIDE})
except DeviceCloudHttpException as e:
- return JsonResponse({ID_ERROR: str(e)})
+ return get_exception_response(e)
def get_farm_status(request):
@@ -322,13 +315,10 @@ def get_farm_status(request):
Returns:
:class:`.JsonResponse`: A JSON response with the status of the farm.
"""
- if is_authenticated(request):
- if not request.is_ajax or request.method != "POST":
- return JsonResponse(
- {"error": "AJAX request must be sent using POST"},
- status=400)
- else:
- return redirect('/access/login')
+ # Check if the AJAX request is valid.
+ error = check_ajax_request(request)
+ if error is not None:
+ return error
try:
# Get the controller ID from the POST request.
@@ -362,7 +352,7 @@ def get_farm_status(request):
return JsonResponse(farm_status, status=200)
except Exception as e:
- return JsonResponse({ID_ERROR: str(e)})
+ return get_exception_response(e)
def set_valve(request):
@@ -376,13 +366,10 @@ def set_valve(request):
Returns:
:class:`.JsonResponse`: A JSON response with the set status.
"""
- if is_authenticated(request):
- if not request.is_ajax or request.method != "POST":
- return JsonResponse(
- {"error": "AJAX request must be sent using POST"},
- status=400)
- else:
- return redirect('/access/login')
+ # Check if the AJAX request is valid.
+ error = check_ajax_request(request)
+ if error is not None:
+ return error
# Get the controller ID and irrigation station from the POST request.
data = json.loads(request.body.decode(request.encoding))
@@ -393,7 +380,7 @@ def set_valve(request):
new_value = set_valve_value(request, controller_id, station_id, value)
if new_value is not None:
return JsonResponse({"value": new_value}, status=200)
- return JsonResponse({"error": "Could not set the valve."}, status=400)
+ return JsonResponse({ID_ERROR: "Could not set the valve."}, status=400)
def set_tank_valve(request):
@@ -407,13 +394,10 @@ def set_tank_valve(request):
Returns:
:class:`.JsonResponse`: A JSON response with the set status.
"""
- if is_authenticated(request):
- if not request.is_ajax or request.method != "POST":
- return JsonResponse(
- {"error": "AJAX request must be sent using POST"},
- status=400)
- else:
- return redirect('/access/login')
+ # Check if the AJAX request is valid.
+ error = check_ajax_request(request)
+ if error is not None:
+ return error
# Get the controller ID and status of the valve from the POST request.
data = json.loads(request.body.decode(request.encoding))
@@ -423,7 +407,7 @@ def set_tank_valve(request):
new_value = set_tank_valve_value(request, controller_id, value)
if new_value is not None:
return JsonResponse({"value": new_value}, status=200)
- return JsonResponse({"error": "Could not set the valve."}, status=400)
+ return JsonResponse({ID_ERROR: "Could not set the valve."}, status=400)
def refill_tank(request):
@@ -437,13 +421,10 @@ def refill_tank(request):
Returns:
:class:`.JsonResponse`: A JSON response with the set status.
"""
- if is_authenticated(request):
- if not request.is_ajax or request.method != "POST":
- return JsonResponse(
- {"error": "AJAX request must be sent using POST"},
- status=400)
- else:
- return redirect('/access/login')
+ # Check if the AJAX request is valid.
+ error = check_ajax_request(request)
+ if error is not None:
+ return error
# Get the controller ID and level of the tank from the POST request.
data = json.loads(request.body.decode(request.encoding))
@@ -452,7 +433,7 @@ def refill_tank(request):
new_value = refill_tank_request(request, controller_id)
if new_value is not None:
return JsonResponse({"value": new_value}, status=200)
- return JsonResponse({"error": "Could not set the valve."}, status=400)
+ return JsonResponse({ID_ERROR: "Could not set the valve."}, status=400)
def get_request_data(request):
@@ -605,13 +586,10 @@ def check_farm_connection_status(request):
Returns:
A JSON with the status of the farm or the error.
"""
- if is_authenticated(request):
- if not request.is_ajax or request.method != "POST":
- return JsonResponse(
- {"error": "AJAX request must be sent using POST"},
- status=400)
- else:
- return redirect('/access/login')
+ # Check if the AJAX request is valid.
+ error = check_ajax_request(request)
+ if error is not None:
+ return error
# Get the controller ID and irrigation station from the POST request.
data = json.loads(request.body.decode(request.encoding))
diff --git a/agriculture/run_web_app.py b/agriculture/run_web_app.py
index 9ddcd6d..f5ff8bf 100644
--- a/agriculture/run_web_app.py
+++ b/agriculture/run_web_app.py
@@ -292,18 +292,18 @@ def main():
# If Python version is greater than 3.7, install the corresponding
# Twisted wheel so the channels module can be installed later on.
- # if sys.platform == "win32" and py_minor_version > 7:
- # twisted = TWISTED_64 if is_64_bits_python() else TWISTED_32
- # twisted_path = os.path.join(
- # FOLDER_WHEELS,
- # twisted.format(py_major_version, py_minor_version))
- # print("- Installing Twisted wheel (%s)... " % twisted_path, end="")
- # sys.stdout.flush()
- # if run_venv_python(venv_context, ['-m', 'pip', 'install',
- # twisted_path], debug) != 0:
- # print_error()
- # sys.exit(-1)
- # print_success()
+ if sys.platform == "win32" and py_minor_version > 7:
+ twisted = TWISTED_64 if is_64_bits_python() else TWISTED_32
+ twisted_path = os.path.join(
+ FOLDER_WHEELS,
+ twisted.format(py_major_version, py_minor_version))
+ print("- Installing Twisted wheel (%s)... " % twisted_path, end="")
+ sys.stdout.flush()
+ if run_venv_python(venv_context, ['-m', 'pip', 'install',
+ twisted_path], debug) != 0:
+ print_error()
+ sys.exit(-1)
+ print_success()
# Install the application requirements.
print("- Installing application requirements: ")
diff --git a/agriculture/source.zip b/agriculture/source.zip
deleted file mode 100644
index a6ec5d6..0000000
Binary files a/agriculture/source.zip and /dev/null differ
diff --git a/agriculture/static/js/dashboard.js b/agriculture/static/js/dashboard.js
index 387ce7b..be7b70e 100644
--- a/agriculture/static/js/dashboard.js
+++ b/agriculture/static/js/dashboard.js
@@ -105,7 +105,7 @@ const ID_STATIONS = "stations";
const ID_WEATHER = "weather";
const ID_TANK = "tank";
-const REFRESH_INTERVAL = 15000;
+const REFRESH_INTERVAL = 10000;
const SUN_GREEN = "";
const CLOUD_GREEN = "";
@@ -270,7 +270,9 @@ function getFarmStatus(first=true) {
return;
processFarmStatusResponse(data, first);
}
- );
+ ).fail(function(response) {
+ processErrorResponse(response);
+ });
}
// Processes the response of the farm status request.
@@ -759,7 +761,9 @@ function toggleValve(stationID) {
if (isValveON(stationID) && !isTankValveON())
toggleTankValve();
}
- );
+ ).fail(function(response) {
+ processErrorResponse(response);
+ });
}
// Updates the status of the valve with the given ID.
@@ -871,7 +875,9 @@ function refillTank() {
waterLevel = data["value"];
updateWaterTankLevel();
}
- );
+ ).fail(function(response) {
+ processErrorResponse(response);
+ });
}
// Updates the status of the tank valve toggle button.
@@ -931,7 +937,9 @@ function toggleTankValve() {
}
}
}
- );
+ ).fail(function(response) {
+ processErrorResponse(response);
+ });
}
// Returns the number of irrigating stations.
diff --git a/agriculture/static/js/history.js b/agriculture/static/js/history.js
index 8d93992..42e50a2 100644
--- a/agriculture/static/js/history.js
+++ b/agriculture/static/js/history.js
@@ -177,7 +177,7 @@ function drawAllCharts(refresh=false, showProgress=true) {
// Repeat the task every minute.
setTimeout(function() {
drawAllCharts(true, false);
- }, 15000);
+ }, 60000);
}
// Draws the wind chart.
@@ -192,6 +192,8 @@ function drawWindChart(refresh=false, showProgress=false) {
drawWindChart();
$("#wind-chart-loading").hide();
});
+ }).fail(function(response) {
+ processErrorResponse(response);
});
} else {
drawChart("wind-chart", windData, "Wind speed", "km/h", "#4F4F4F", windDirectionData, "Direction", "Direction", "#3CE222");
@@ -207,6 +209,8 @@ function drawRainChart(refresh=false, showProgress=false) {
rainData = response.data;
drawRainChart();
$("#rain-chart-loading").hide();
+ }).fail(function(response) {
+ processErrorResponse(response);
});
} else {
drawChart("rain-chart", rainData, "Rain", "L/m²", "#3399FF");
@@ -222,6 +226,8 @@ function drawLuminosityChart(refresh=false, showProgress=false) {
luminosityData = response.data;
drawLuminosityChart();
$("#luminosity-chart-loading").hide();
+ }).fail(function(response) {
+ processErrorResponse(response);
});
} else {
drawChart("luminosity-chart", luminosityData, "Luminosity", "Lux", "#FFD500");
@@ -237,6 +243,8 @@ function drawRadiationChart(refresh=false, showProgress=false) {
radiationData = response.data;
drawRadiationChart();
$("#radiation-chart-loading").hide();
+ }).fail(function(response) {
+ processErrorResponse(response);
});
} else {
drawChart("radiation-chart", radiationData, "Radiation", "W/m²", "#FFD500");
@@ -252,6 +260,8 @@ function drawTemperatureChartG(refresh=false, showProgress=false) {
temperatureDataG = response.data;
drawTemperatureChartG();
$("#temperature-chart-loading").hide();
+ }).fail(function(response) {
+ processErrorResponse(response);
});
} else {
drawChart("temperature-chart", temperatureDataG, "Temperature", "ºC", "#FF0000");
@@ -267,6 +277,8 @@ function drawTemperatureChart(macAddr, refresh=false, showProgress=false) {
temperatureData[macAddr] = response.data;
drawTemperatureChart(macAddr);
$("#temperature-" + macAddr + "-chart-loading").hide();
+ }).fail(function(response) {
+ processErrorResponse(response);
});
} else {
drawChart("temperature-" + macAddr + "-chart", temperatureData[macAddr], "Temperature", "ºC", "#FF0000");
@@ -282,6 +294,8 @@ function drawMoistureChart(macAddr, refresh=false, showProgress=false) {
moistureData[macAddr] = response.data;
drawMoistureChart(macAddr);
$("#moisture-" + macAddr + "-chart-loading").hide();
+ }).fail(function(response) {
+ processErrorResponse(response);
});
} else {
drawChart("moisture-" + macAddr + "-chart", moistureData[macAddr], "Moisture", "%", "#33CC66");
@@ -297,6 +311,8 @@ function drawValveChart(macAddr, refresh=false, showProgress=false) {
valveData[macAddr] = response.data;
drawValveChart(macAddr);
$("#valve-" + macAddr + "-chart-loading").hide();
+ }).fail(function(response) {
+ processErrorResponse(response);
});
} else {
drawChart("valve-" + macAddr + "-chart", valveData[macAddr], "Valve", "Closed/Open", "#0000CC");
@@ -351,7 +367,7 @@ function drawChart(id, data, title, units, color=null, data2=null, units2=null,
// Adds titles to each axis.
0: {title: units, ticks: [{v: 0}, {v: 8}, {v: 16}, {v: 24}, {v: 32}, {v: 40}, {v: 48}, {v: 56} , {v: 64}]}
},
-
+
legend: { position: 'bottom' },
tooltip: { ignoreBounds: true, isHtml: true, trigger: 'both' }
};
@@ -419,6 +435,8 @@ function drawStationsCharts() {
drawMoistureChart(macAddr, true, true);
drawValveChart(macAddr, true, true);
}
+ }).fail(function(response) {
+ processErrorResponse(response);
});
}
diff --git a/agriculture/static/js/widgets.js b/agriculture/static/js/widgets.js
index 4638324..3509692 100644
--- a/agriculture/static/js/widgets.js
+++ b/agriculture/static/js/widgets.js
@@ -14,7 +14,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-
var currentTime;
var currentTimeFactor;
var timeWorker;
@@ -34,6 +33,8 @@ function setTimeFactor(e) {
$.post("/ajax/set_factor", getJsonData(selected)).fail(function(response) {
// If the operation fails, get the real factor.
getTimeFactor();
+ }).fail(function(response) {
+ processErrorResponse(response);
});
}
@@ -45,6 +46,8 @@ function getTimeFactor() {
selectTimeIcon(currentTimeFactor);
getCurrentTime();
}
+ }).fail(function(response) {
+ processErrorResponse(response);
});
}
@@ -59,6 +62,8 @@ function getCurrentTime() {
};
timeWorker.postMessage(currentTime + "@@@" + currentTimeFactor);
}
+ }).fail(function(response) {
+ processErrorResponse(response);
});
}