I'm making a little ESP8266 project for myself, in which I want to display the Temperature and Humidity of an DHT11 sensor on a website. The code I have now works perfectly, but the timestamps at the charts are kinda weird. I want these timestamps to be the real time of Amsterdam when the data is uploaded to the charts. Is there anyone with any experience to do this? Let me know! Thanks in advance!
#include <DHT.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#define DHTTYPE DHT11
#define DHTPIN 2
DHT dht(DHTPIN, DHTTYPE);
ESP8266WebServer server(80);
void setup() {
Serial.begin(115200);
WiFi.begin("SSID", "Password");
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
dht.begin();
server.on("/", []() {
String html = "<html><body>";
html += "<style> body{text-align:center; font-family:sans-serif;}#temp,#hum{color:red;}h1{font-size:75px;}.top{margin-top:50px;}</style>";
html += "<h1 class='top'>Temperatuur: <span id='temp'>Loading...</span> *C</h1>";
html += "<h1>Luchtvochtigheid <span id='hum'>Loading...</span> %</h1>";
html += "<script src='https://cdn.jsdelivr.net/npm/chart.js#2.9.3/dist/Chart.min.js'></script>";
html += "<canvas id='tempChart'></canvas>";
html += "<canvas id='humChart' style='margin-top:50px;'></canvas>";
html += "<script>setInterval(function(){fetch('/temp-hum').then(res=>res.text()).then(tempHum=>{let [temp, hum] = tempHum.split(','); document.getElementById('temp').innerHTML=temp; document.getElementById('hum').innerHTML=hum});fetch('/getTempData').then(res => res.json()).then(data => {tempChart.data.labels.push(data.time); tempChart.data.datasets[0].data.push(data.temp); tempChart.update()});fetch('/getHumData').then(res => res.json()).then(data => {humChart.data.labels.push(data.time); humChart.data.datasets[0].data.push(data.hum); humChart.update()})}, 10000);</script>";
html += "<script>var tempCtx = document.getElementById('tempChart').getContext('2d');var tempChart = new Chart(tempCtx, {type: 'line',data: { labels: [],datasets: [{label: 'Temperature',data: [],borderColor: 'red',fill: false}]},options: {scales: {yAxes: [{scaleLabel: {display: true,labelString: 'Temperature (°C)'}}],xAxes: [{scaleLabel: {display: true,labelString: 'Time'}}]},title: {display: true,text: 'Temperature over time'},legend: {display: true }}});var humCtx = document.getElementById('humChart').getContext('2d');var humChart = new Chart(humCtx, {type: 'line',data:{ labels: [],datasets: [{label: 'Humidity',data: [],borderColor: 'blue',fill: false}]},options: {scales: {yAxes: [{scaleLabel: {display: true,labelString: 'Humidity (%)'}}],xAxes: [{scaleLabel: {display: true,labelString: 'Time'}}]},title: {display: true,text: 'Humidity over time'},legend: {display: true }}})</script>";
html += "</body></html>";
server.send(200, "text/html", html);
});
server.on("/temp-hum", []() {
String temp = String(dht.readTemperature());
String hum = String(dht.readHumidity());
String tempHum = temp + "," + hum;
server.send(200, "text/plain", tempHum);
});
server.on("/getTempData", []() {
String time = String(millis());
String temp = String(dht.readTemperature());
String data = "{\"time\":\""+time+"\",\"temp\":\""+temp+"\"}";
server.send(200, "application/json", data);
});
server.on("/getHumData", []() {
String time = String(millis());
String hum = String(dht.readHumidity());
String data = "{\"time\":\""+time+"\",\"hum\":\""+hum+"\"}";
server.send(200, "application/json", data);
});
server.begin();
Serial.println("Server started");
}
void loop() {
server.handleClient();
}
You are looking to find unix time(time since Jan 1970), that is quite easy to convert from nanaoseconds to time in amsterdam. So converting Unix time into CET. It that's a bit too much work, and time accuracy is not extremely important. You could make a request and parse it. Hope this helped a bit.
There are many ways to get real time clock
Use NTP Client-Server to get real world time
(or) Add RTC (Real time clock) module to your ESP
Related
I've recently purchased a ESP8266, and started playing around with it. I made a website, that has three buttons to control 3 LEDs with the board. The site uses XML AJAX and JavaScript to communicate with the ESP. I'm going to be honest, I have very little clue to what I am doing. The ESP successfully connects to my WiFi and serves the website, but for some reason, that I am clueless to, the ESP doesn't serve the XML file.
If this is the wrong place to post this, I apologize.
ESP Code:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include "page.h"
//LED Pin defenition.
const int led1 = 14;
const int led2 = 12;
const int led3 = 13;
#define SSID "Orlando"
#define PASS "orlando123"
#define AP_SSID "ESP2866"
#define AP_PASS "password"
bool led11 = false;
bool led22 = false;
bool led33 = false;
char XML[1024];
IPAddress Actual_IP;
//Start a server at port 80.
ESP8266WebServer server(80);
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
Serial.begin(9600);
for (int i = 12;i < 15;i++){
digitalWrite(i, LOW);
}
//Initliaizes WIFI
WiFi.begin(SSID, PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("IP address: "); Serial.println(WiFi.localIP());
Actual_IP = WiFi.localIP();
server.on("/", sendWebsite);
server.on("/xml", SendXML);
//If the ESP recieves the "BUTTON_1" string, it will run the ProcessButton_1 method.
server.on("/BUTTON_1", ProcessButton_1);
server.on("/BUTTON_2", ProcessButton_2);
server.on("/BUTTON_3", ProcessButton_3);
server.begin();
}
void loop() {
server.handleClient();
}
//Method for sending the site.
void sendWebsite() {
server.send(200, "text/html", WEBSITE);
Serial.println("Sending website.");
}
//Method for sendind the XML info.
void SendXML() {
Serial.println("sending xml");
strcpy(XML, "<?xml version = '1.0'?>\n<Data>\n");
if (led1) {
strcat(XML, "<LED1>1</LED1>\n");
}
else {
strcat(XML, "<LED1>0</LED1>\n");
}
if (led2) {
strcat(XML, "<LED2>1</LED2>\n");
}
else {
strcat(XML, "<LED2>0</LED2>\n");
}
if (led3) {
strcat(XML, "<LED3>1</LED3>\n");
}
else {
strcat(XML, "<LED3>0</LED3>\n");
}
strcat(XML, "</Data>\n");
server.send(200, "text/xml", XML);
Serial.println("Sending XML");
Serial.println(XML);
}
void ProcessButton_1() {
led11 != led11;
digitalWrite(led1, led11);
server.send(200, "text/plain", "");
Serial.println("Processing button1");
}
void ProcessButton_2() {
led22 != led22;
digitalWrite(led2, led22);
server.send(200, "text/plain", "");
Serial.println("Processing button2");
}
void ProcessButton_3() {
led33 != led33;
digitalWrite(led3, led33);
server.send(200, "text/plain", "");
Serial.println("Processing button3");
}
Website code:
<!DOCTYPE html>
<html lang="en" class="js-focus-visible">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Webserver</title>
</head>
<body onload="process()">
<div class="container">
<div class="header">
<h1>Panel</h1>
<br>
</div>
<div class="controls">
<table>
<tr>
<th>
<p>BLUE LED</p>
<button type="button" class="button1" id="sw1" onclick="ButtonPress1()">
ON/OFF
</button>
</th>
<th>
<p>RED LED</p>
<button type="button" class="button2" id="sw2" onclick="ButtonPress2()">
ON/OFF
</button>
</th>
<th>
<p>GREEN LED</p>
<!--ButtonPress3() - calls to a javascript function-->
<button type="button" class="button3" id="sw3" onclick="ButtonPress3()">
ON/OFF
</button>
</th>
</tr>
</table>
</div>
</div>
</body>
<script type = "text/javascript">
// Creates XmlHttpObject
var xmlHttp=createXmlHttpObject();
function createXmlHttpObject(){
if(window.XMLHttpRequest){
xmlHttp=new XMLHttpRequest();
}
else{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
return xmlHttp;
}
//All the functions are for the correspoding button on the website:
function ButtonPress1() {
var xhttp = new XMLHttpRequest();
var message;
//Opens a request, specifies type of request, data to send
//in this case a string: "BUTTON_1", and if request is synchrounous.
xhttp.open("PUT", "BUTTON_1", false);
xhttp.send();
}
function ButtonPress2() {
var xhttp = new XMLHttpRequest();
var message2;
//Opens a request, specifies type of request, data to send
//in this case a string: "BUTTON_2", and if request is synchrounous.
xhttp.open("PUT", "BUTTON_2", false);
xhttp.send();
}
function ButtonPress3() {
var xhttp = new XMLHttpRequest();
var message3;
//Opens a request, specifies type of request, data to send
//in this case a string: "BUTTON_3", and if request is synchrounous.
//xttp.open sends a string, in this case "BUTTON_3", this signals the
//ESP, that a button has been pressed.
xhttp.open("PUT", "BUTTON_3", false);
xhttp.send();
}
function ESP_response() {
var message1;
var message2;
var message3;
var xmlResponse;
//Read the XML stream.
xmlResponse=xmlHttp.responseXML;
if(message1 == 0 ) {
document.getElementById("sw1").innerHTML="OFF";
}
else {
document.getElementById("sw1").innterHTML="ON";
}
if(message2 == 0 ) {
document.getElementById("sw2").innerHTML="OFF";
}
else {
document.getElementById("sw2").innterHTML="ON";
}
if(message3 == 0 ) {
document.getElementById("sw3").innerHTML="OFF";
}
else {
document.getElementById("sw3").innterHTML="ON";
}
}
function process(){
if(xmlHttp.readyState==0 || xmlHttp.readyState==4) {
xmlHttp.open("PUT","xml",true);
xmlHttp.onreadystatechange=response;
xmlHttp.send(null);
}
setTimeout("process()",200);
}
</script>
</html>
Thanks in advance.
I expect the ESP to respond to the button presses on the site.
I haven't tried anything, as I don't have any experience to help me with this.
for example... 1130 Racquet Club North Drive Indianapolis IN 46260
has both a tennis court and an apartment complex.. tried the places api, but none of them seem to return what I see on the map at that location. Any help would be appreciated.
This code example.
I hope this code helps you
let lat;
let long;
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
//alert("Geolocation is not supported by this browser.");
}
}
function showPosition(position) {
var latitud= document.getElementById('latitud');
lat = latitud.value = position.coords.latitude
var longitud= document.getElementById('longitud');
long = longitud.value = position.coords.longitude
}
I am using esp8266 to run my websocket server and angular 7 to run socket.io to run websocket client. When I run the angular application. The logs in Arduino shows Disconnected!. I am not sure what is causing this.
following is the angular side code for client.
import * as io from 'socket.io-client';
import { Observable } from 'rxjs/Observable';
import * as Rx from 'rxjs/Rx';
import { environment } from 'src/environments/environment';
#Injectable()
export class SocketServiceService {
private socket;
constructor() { }
connect(): Rx.Subject<MessageEvent> {
this.socket = io('ws://192.168.43.155:81');
console.log("created server")
let observable = new Observable(observer => {
this.socket.on('message', (data) => {
console.log("Received message from Websocket Server")
observer.next(data);
})
return () => {
this.socket.disconnect();
}
});
let observer = {
next: (data: Object) => {
this.socket.emit('message', JSON.stringify(data));
console.log("msg emited"+ data);
},
};
return Rx.Subject.create(observer, observable);
}
}
this is esp8266 code
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsServer.h>
#include <Hash.h>
ESP8266WiFiMulti WiFiMulti;
WebSocketsServer webSocket = WebSocketsServer(81);
#define USE_SERIAL Serial1
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
USE_SERIAL.printf("[%u] Disconnected!\n", num);
break;
case WStype_CONNECTED:
{
IPAddress ip = webSocket.remoteIP(num);
USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
webSocket.sendTXT(num, "Connected");
}
break;
case WStype_TEXT:
USE_SERIAL.printf("[%u] get Text: %s\n", num, payload);
break;
case WStype_BIN:
USE_SERIAL.printf("[%u] get binary length: %u\n", num, length);
hexdump(payload, length);
break;
}
}
void setup() {
USE_SERIAL.begin(115200);
USE_SERIAL.setDebugOutput(true);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
WiFiMulti.addAP("SSID", "passpasspass");
while(WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
webSocket.begin();
webSocket.onEvent(webSocketEvent);
}
void loop() {
webSocket.loop();
}
please Suggest what might be going wrong, Any pointers will be helpful.
It's a lot to ask for someone to actually try to debug this (to do so, I'd have to create an Angular project using your Angular code, and also set up an ESP8266 sketch using your Arduino code), so I'm not going to try, but here's a couple of suggestions:
Try setting up a WebSocket server in Node, using the example code in the socket.io-client documentation. If that works, then you've narrowed the problem down to the ESP8266 code. If it fails in the same way, then you have a problem in your Angular client.
If the problem is in your Angular code, I'd suggest using the rsjx WebSocketSubject class. It gives you a fully configured WebSocket client, works really well, and would eliminate your low-level websocket client code.
Here's an example of connecting to the WebSocket, subscribing to inbound messages, and sending an outbound message:
connect() {
this.webSocket = webSocket(environment.chatUrl);
this.subscription = this.webSocket.subscribe(msg => {
console.log('got message: ' + msg);
},
err => {
this.setDisconnected();
console.log('err!', err);
},
() => {
console.log('websocket closed'));
this.setDisconnected();
}
);
this.webSocket.next({
name: this.name
});
}
and here's sending a message:
sendMessage(msg: string) {
if (this.connected) {
this.webSocket.next(msg);
}
}
and here's disconnecting:
private disconnect() {
if (this.subscription) {
this.webSocket.complete();
this.subscription.unsubscribe();
this.subscription = undefined;
this.setDisconnected();
}
}
I've similar question like Urlencoding in Dart. I can encode Map, by HttpRequest.postFormData. But JQuery post method can encode Map<String, dynamic>. JQuery example:
$.post("controller",
{actualTime: 1357089552, events: [{priceInsert: 1.32128, priceExecution: 1.32128}]},
function(data) {/*handle*/});
Firebug HttpRequest post view:
actualTime 1357089552
events[0][priceExecution] 1.32128
events[0][priceInsert] 1.32128
Payload source is:
actualTime=1357089552&events%5B0%5D%5BpriceInsert%5D=1.32128&events%5B0%5D%5BpriceExecution%5D=1.32128
Dart can't do it easily. Someone has this problem solved?
PHP with nette requires to set some header:
X-Requested-With:XMLHttpRequest
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
I've some dirty quick fix. Not complete, not tested, working for me:
Map<String, dynamic> data = {"actualTime": 1357089552, "events": [{"priceInsert": 1.32128, "priceExecution": 1.32128}]};
StringBuffer urlData = new StringBuffer("");
bool first = true;
void urlEncode(dynamic sub, String path){
if(sub is List){
for(int i = 0;i<sub.length;i++){
urlEncode(sub[i], "$path%5B$i%5D");
}
}else if(sub is Map){
sub.forEach((k,v){
if(path == ""){
urlEncode(v, "${Uri.encodeQueryComponent(k)}");
}else{
urlEncode(v, "$path%5B${Uri.encodeQueryComponent(k)}%5D");
}
});
}else{
if(!first){
urlData.write("&");
}
first = false;
urlData.write("$path=${Uri.encodeQueryComponent(sub.toString())}");
}
}
urlEncode(data, "");
HttpRequest xhr = new HttpRequest();
xhr
..open('POST', url)
..onLoadEnd.listen((ProgressEvent event){/*handle success*/}, onError: (){/*handle error*/})
..setRequestHeader("X-Requested-With", "XMLHttpRequest")
..setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
..send(urlData.toString());
This error only appears if I try to put two charts on the same page. Both charts work perfectly if they are the only one on the page. The minute I add the second only the first one loads and I get the "Missing Query for request id: 0" error.
Here is my js file for the chart:
function drawChart(title, queryPage, divToFill) {
var dataTab = null;
var query = new google.visualization.Query(queryPage);
var strSQL = "SELECT *";
query.setQuery(strSQL);
query.send(processInitalCall);
function processInitalCall(res) {
if(res.isError()) {
alert(res.getDetailedMessage());
} else {
dataTab = res.getDataTable();
// Draw chart with my DataTab
drawChart(dataTab);
}
}
function drawChart(dataTable) {
// Draw the chart
var options = {};
options['title'] = title;
options['backgroundColor'] = "#8D662F";
var colors = Array();
var x = 0;
if(currentCampaignId >= 0) {
while(x < dataTab.getNumberOfColumns() - 2) {
colors[x] = '#c3c1b1';
x++;
}
colors[x] = '#d2bc01';
}
else {
colors[0] = '#c3c1b1';
}
options['colors'] = colors;
options['hAxis'] = {title: "Week", titleColor: "white", textColor: "white"};
options['vAxis'] = {title: "Flow", titleColor: "white", textColor: "white", baselineColor: "#937d5f", gridColor: "#937d5f"};
options['titleColor'] = "white";
options['legend'] = "none";
options['lineWidth'] = 1;
options['pointSize'] = 3;
options['width'] = 600;
options['height'] = 300;
var line = new google.visualization.LineChart(document.getElementById(divToFill));
line.draw(dataTab, options);
}
}
Here is a snip from the index.php file:
<body>
<script type="text/javascript">
google.load('visualization', '1', {'packages': ['table', 'corechart']});
google.setOnLoadCallback(function(){
drawChart("Water", "waterData.php", "water");
drawChart("Air", "airData.php", "air");
});
</script>
<div id="water" style="text-align: center;"></div>
<div id="air" style="text-align: center;"></div>
</body>
It throws the error right at the query.send(processInitalCall); line, only on the second time it's called. Both the waterData.php and airData.php are identical except for the sig field. I did notice there was a field called reqId and it's set to 0.
Do I need to somehow change this reqId in these classes?
Probably too late, but for anyone interested...
When loading data from the data source, there will be a GET parameter in the request - tqx - with a value like: "reqId:0". You must return the same reqId in your response.
From the docs:
reqId - [Required in request; Data source must handle] A numeric
identifier for this request. This is used so that if a client sends
multiple requests before receiving a response, the data source can
identify the response with the proper request. Send this value back in
the response.
I don't have enough status in StackOverflow to write a comment, but this thread saved me an immense amount of time as well. THANK YOU
google visualization multiple charts with own data queries