summaryrefslogblamecommitdiffstats
path: root/fiz/naloga/vodnaraketa/src/main.cpp
blob: f782cdba44d1f3d698af52e053fdbe104c9d5360 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15














                                     
                                   








                              
                                 
                 














                                                                                                                  


                                                                                                     
                                 
                 
                                                         
                                 
                                                          
                                   
                                                         



                                 
                                           

                        







                                                                        
                                    














                                                                                         


                                                                        

                                                                                                                                     



                                                                          
                                             
                                                                          

                                                                









                                                                       





                                                                                  








                                                                                     


                                                                                    





                                                                    





                                                                                      


                              


                                                               


                                                               
                                                                                               

                                       

                                                                                  
                                
                                                                              




                                                                                 

                                                                                                                              
                                                                                                                               








                                                                                                 
                                                               

















                                                                                                                                




                                                               
                                                                                                                                
                        
                                                                       


                    













                                                                                                                                          


                      




















                                                                                                                         
                 










                                                                               
         





                                                                                                                                           


               
                                    





                                    









                                               
 
#define ARDUINOJSON_ENABLE_COMMENTS 1
#include <stdlib.h>
#include <Arduino.h>
#include <ArduinoJson.h>
#include "LittleFS.h"
#include <DNSServer.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <TimeLib.h>
#include <WiFiUdp.h>
#include <ESP8266httpUpdate.h>
#include <ESPAsyncWebServer.h>
#include <HX711.h>
#include <FTPServer.h>

DynamicJsonDocument settings(1024);

#include <func.c>

FTPServer ftpServer(LittleFS);
DNSServer dnsServer;
AsyncWebServer httpServer(80);
HX711 scale;

time_t measure = 0;
unsigned long measureStartMillis;
File measureFile;
struct measure {
	unsigned long millis;
	float scale;
	double pa;
};
#define MEASURE_BUFFER_SIZE (1024)
struct measure measureBuffer[MEASURE_BUFFER_SIZE]; /* buffer to store measured stuff before writing to littlefs */

#define A2VOLT(ar) (ar*3.3/1023)
#define VOLT2A(vo) (vo*1023/3.3)
#define A2PA(ar) ((A2VOLT(ar)-0.5)*1200000/4.5)
#define TEXT_ENC "text/plain; charset=utf-8"

int do_reload = 0;


void reload (bool w = 0) {
	/* stop services unless they were never started, indicate this by w in for example setup() */
	Serial.println("reload");
	if (!w) {
		Serial.println("stopping services: ftp");
		ftpServer.stop();
		Serial.println("stopping services: http");
		httpServer.reset();
		Serial.println("stopping services: dns");
		dnsServer.stop();
	}

	/* reload settings */
	Serial.println("loading settings");
	load_settings();

	/* configure pin modes */
	pinMode(LED_BUILTIN, OUTPUT);
	digitalWrite(LED_BUILTIN, HIGH /* LED IS ON when pulled LOW */);


	long unsigned int mac;
	uint8_t macar[6];

	/* bring up AP networking */
	/* // setting fancy settings does not work, FUCK ESPRESSIF AND THEIR BLOB RTOS!!!
		IPAddress ap_ip(10, 82, 66, 1);
		ap_ip.fromString(settings["ap_ip"].as<String>());
		IPAddress ap_gateway(10, 82, 66, 1);
		ap_gateway.fromString(settings["ap_gw"].as<String>());
		IPAddress ap_subnet(255, 255, 255, 0);
		ap_subnet.fromString(settings["ap_nm"].as<String>());
		WiFi.softAPdisconnect(true);
		WiFi.softAPConfig(ap_ip, ap_gateway, ap_subnet);
		mac = strtoul(settings["ap_mac"].as<String>().c_str(), NULL, 16);
		memcpy(macar, (char *) &mac, 6);
		if (strlen(settings["ap_mac"].as<String>().c_str()) == 12)
			wifi_set_macaddr(SOFTAP_IF, macar);
	*/
	Serial.println("access point");
	const char * ap_pass = settings["ap_pass"].as<String>().c_str();
	if (ap_pass && strlen(ap_pass) < 8)
		ap_pass = NULL;
	WiFi.mode(WIFI_AP);
	WiFi.softAP(settings["ap_ssid"].as<String>().c_str(), ap_pass, settings["ap_ch"].as<int>(), settings["ap_hidden"].as<int>());
	Serial.println("WiFi.softAPIP() = " + WiFi.softAPIP().toString());


	/* bring up STA networking - if that's desired */
	Serial.println("station networking");
	const char * sta_ssid = settings["sta_ssid"].as<String>().c_str();
	if (strlen(settings["sta_ssid"].as<String>().c_str())) {
		Serial.println("setting up wifi station mode");
		IPAddress sta_ip(10, 69, 69, 82);
		sta_ip.fromString(settings["sta_ip"].as<String>());
		IPAddress sta_gw(10, 69, 69, 1);
		sta_ip.fromString(settings["sta_gw"].as<String>());
		IPAddress sta_nm(255, 255, 255, 0);
		sta_ip.fromString(settings["sta_nm"].as<String>());
		IPAddress sta_dns1(93, 103, 235, 126);
		sta_dns1.fromString(settings["sta_dns1"].as<String>());
		IPAddress sta_dns2(193, 2, 1, 66);
		sta_dns2.fromString(settings["sta_dns2"].as<String>());

		mac = strtoul(settings["sta_mac"].as<String>().c_str(), NULL, 16);
		memcpy(macar, (char *) &mac, 6);
		if (strlen(settings["sta_mac"].as<String>().c_str()) == 12)
			wifi_set_macaddr(STATION_IF, macar);

		WiFi.disconnect(true);
		WiFi.hostname(settings["sta_host"].as<String>());
		const char * sta_pass = settings["sta_pass"].as<String>().c_str();
		if (strlen(sta_pass) < 8)
			sta_pass = NULL;
		WiFi.begin(sta_ssid, sta_pass);
		if (settings["sta_static"].as<int>())
			if (!WiFi.config(sta_ip, sta_gw, sta_nm, sta_dns1, sta_dns2))
				Serial.println("failed to wifi config");
		Serial.println(String("wifi local ip: ")+WiFi.localIP().toString());
	} else {
		WiFi.disconnect();
	}

	/* start services */
	dnsServer.start(53, settings["host"], WiFi.softAPIP());
	ftpServer.begin(settings["ftp_user"], settings["ftp_pass"]);
	/* web server */
#define ADD_AUTH(h) h.setAuthentication(settings["http_user"], settings["http_pass"]);
	auto s = httpServer.serveStatic("/index.html", LittleFS, "/")
		.setDefaultFile("index.html");
	ADD_AUTH(s);
	auto h = httpServer.on("/s", [](AsyncWebServerRequest * r) {
		r->send(201, TEXT_ENC, "OK");
		ESP.restart();
	});
	ADD_AUTH(h);
	h = httpServer.on("/l", [](AsyncWebServerRequest * r) {
		r->send(201, TEXT_ENC, "OK");
		do_reload = 1;
	});
	h = httpServer.on("/m", [](AsyncWebServerRequest * r) {
		if (!r->hasParam("n"))
			r->send(400, TEXT_ENC, "Manjka parameter n - število sekund meritve");
		else
			if (!measure) {
				measure = atoi(r->getParam("n")->value().c_str());
				r->send(201, TEXT_ENC, String("OK")+measure);
			} else {
				r->send(400, TEXT_ENC, "Meritev že poteka!");
			}
	});
	ADD_AUTH(h);

	/* specifični ukazi za meritve: začetek loadcella, kalibracija, tara */
	Serial.println(String("začenjam vago na pinih ")+str2pin(settings["scale_dout"].as<String>().c_str())+String(" in ")+
			str2pin(settings["scale_sck"].as<String>().c_str()));
	scale.begin(str2pin(settings["scale_dout"].as<String>().c_str()), str2pin(settings["scale_sck"].as<String>().c_str()));
	Serial.println(String("kalibriram vago na vrednost ")+settings["scale_cal"].as<float>());
	scale.set_scale(settings["scale_cal"].as<float>());
	scale.set_offset(settings["scale_tar"].as<long>());
	if (scale.wait_ready_timeout(1000))
		Serial.println(String("skala meri surovo: ")+scale.read_average(10));
	else
		Serial.println(String("ne morem se povezati na skalo"));

	/* specifični http ukazi */
	h = httpServer.on("/c", [](AsyncWebServerRequest * r) {
		if (!r->hasParam("t") && !r->hasParam("f")) {
			r->send(400, TEXT_ENC, "Manjka parameter t - teža na tehtnici ali parameter f - kalibracijski faktor");
		} else
			if (scale.wait_ready_timeout(1000)) {
				float scaleCal;
				if (!r->hasParam("f")) {
					scale.set_scale();
					scale.tare();
					scaleCal = scale.get_units(10)/atof(r->getParam("t")->value().c_str());
					scale.set_scale(scaleCal);
					r->send(200, TEXT_ENC, String("kalibracijski faktor: ")+String(scaleCal));
				} else {
					scale.set_scale(atof(r->getParam("f")->value().c_str()));
					r->send(200, TEXT_ENC, String("teža: "+String(scale.get_units(10))));
				}
			} else {
				r->send(500, TEXT_ENC, "Tehtnica ni najdena");
			}
	});
	ADD_AUTH(h);
	h = httpServer.on("/t", [](AsyncWebServerRequest * r) {
		if (scale.wait_ready_timeout(1000)) {
			scale.tare();
			r->send(400, TEXT_ENC, String("razlika, ki jo odštejemo od surove vrednosti, je ")+scale.get_offset());
		} else {
			r->send(500, TEXT_ENC, "Tehtnica ni najdena.");
		}
	});
	ADD_AUTH(h);
	h = httpServer.on("/g", [](AsyncWebServerRequest * r) {
		float reading = -1;
		long readingraw = -1;
		if (scale.wait_ready_timeout(1000)) {
			reading = scale.get_units(5);
			readingraw = scale.read_average(5);
		} else
			Serial.println("/g: reading error");
		double pa = analogRead(A0);
		pa = A2PA(pa);
		r->send(200, "application/json", String("{\"p\":")+pa+String(",\"s\":")+reading+String(",\"r\":")+readingraw+String("}"));
	});
	ADD_AUTH(h);
	httpServer.begin();
}

void handleMeasure() {
	/* ni časovno omejeno, zapiše se čim več meritev, recimo izvede se enkrat na 10 milisekund, to je idealno. */
	/* ob desetsekundni meritvi je to 1000 zajemov, kar znese ob 100 bajtih na zajem 100 kilobajtov na flash. */
	httpServer.end();
	Serial.println(String("meritev loop started at ")+millis());
	measure += time(NULL)+1;
	int i = 0;
	digitalWrite(LED_BUILTIN, LOW); /* glows in the dark1 */
	ESP.wdtDisable();
	while (measure >= time(NULL)) {
		Serial.println("meritev ...");
		if (scale.wait_ready_timeout(1000)) {
			measureBuffer[i].millis = millis();
			measureBuffer[i].scale = scale.get_units(1);
			/* zaradi konstantnega branja analognih vrednosti je pričakovano, da ob meritvi crkne WiFi */
			measureBuffer[i].pa = analogRead(A0);
			measureBuffer[i].pa = A2PA(measureBuffer[i].pa);
		} else
			Serial.println("HX711 ni najden.");
		if (i >= MEASURE_BUFFER_SIZE) {
			Serial.println("zapolnjen measure buffer, dovolj bo");
			break;
		}
		i++;
	}
	ESP.wdtEnable(2000);
	digitalWrite(LED_BUILTIN, HIGH); /* stops glowing */
	if (!measureFile.isFile()) {
		char filename[32];
		snprintf(filename, 32, "meritev%ld.csv", time(NULL));
		Serial.println(String("starting measure into file ")+filename);
		measureFile = LittleFS.open(filename, "w");
		scale.power_up();
		measureStartMillis = millis();
	}
	for (int j = 0; j < i; j++)
		measureFile.print(measureBuffer[j].millis+String(",")+measureBuffer[j].scale+String(",")+measureBuffer[j].pa+String("\n"));
	measure = 0;
	measureFile.close();
	Serial.println(String("meritev loop done at ")+millis());
	httpServer.begin();
}

void setup () {
	Serial.begin(MONITOR_SPEED);
	Serial.println("Živ sem!");
	LittleFS.begin();
	reload(1);
}

void loop () {
	if (measure)
		handleMeasure();
	else {
		ftpServer.handleFTP();
		dnsServer.processNextRequest();
		if (do_reload) {
			reload();
			do_reload = 0;
		}
	}
}