I can't figure out how to send the data in one go. I am asking because sending it simultaneously delays a bit.
I did see an other topic of someone posting a piece of code, but that did not work.
This is a bit of the code:
void handleRoot() {
String s = MAIN_page; // Read HTML contents
server.send(200, "text/html", s); // Send web page
}
void handleFORESTTEMPERATURE() {
String ForrestTemperatureDev = String(ForestTemperature, 1);
server.send(200, "text/plane", ForestTemperatureDev); // Send ADC value only to client ajax request
}
void handleFORESTPRESSURE() {
String ForrestPressureDev = String(ForestPressure);
server.send(200, "text/plane", ForrestPressureDev); // Send ADC value only to client ajax request
}
void handleFORESTHUMIDITY() {
String ForrestHumidityDev = String(ForestHumidity);
server.send(200, "text/plane", ForestHumidityDev); // Send ADC value only to client ajax request
}
server.on("/readFORESTPRESSURE", handleFORESTPRESSURE);
server.on("/readFORESTTEMPERATURE", handleFORESTTEMPERATURE);
server.on("/readFORESTHUMIDITY", handleFORESTHUMIDITY);
server.on("/readFORESTWEATHERSTATUS", handleFORESTWEATHERSTATUS);
The following code would send all three values separated with a ; when \readALL is requested.
The three values can be split on the ; in your receiving application; using JSON would be just a little bit more work.
Note1: Untested, I just typed it in, but you get the idea.
Note2: It's text/plain, not text/plane.
void handleRoot() {
String s = MAIN_page; //Read HTML contents
server.send(200, "text/html", s); //Send web page
}
void handleFORESTTEMPERATURE() {
String ForrestTemperatureDev = String(ForestTemperature, 1);
server.send(200, "text/plain", ForestTemperatureDev); //Send ADC value only to client ajax request
}
void handleFORESTPRESSURE() {
String ForrestPressureDev = String(ForestPressure);
server.send(200, "text/plain", ForrestPressureDev); //Send ADC value only to client ajax request
}
void handleFORESTHUMIDITY() {
String ForrestHumidityDev = String(ForestHumidity);
server.send(200, "text/plain", ForestHumidityDev); //Send ADC value only to client ajax request
}
void handleALL() {
String AllDev = String(ForestTemperature, 1) + ";" + String(ForestPressure) + ";" + String(ForestHumidity);
server.send(200, "text/plain", AllDev); //Send ADC values only to client ajax request
}
server.on("/readFORESTPRESSURE", handleFORESTPRESSURE);
server.on("/readFORESTTEMPERATURE", handleFORESTTEMPERATURE);
server.on("/readFORESTHUMIDITY", handleFORESTHUMIDITY);
server.on("/readFORESTWEATHERSTATUS", handleFORESTWEATHERSTATUS);
server.on("/readALL", handleALL);
Related
I would like to ask about sending data from arduino/esp to .net App service running on Azure.
I am sending JSON to API with "list" of measurements (simple JSON, Id and Value).
Over PostMan I don't have any issue, but over Arduino I am facing issue that I receive result code 415.
Data are sent in JSON.
Arduino Code:
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
const char* ssid = "*******";
const char* password = "*******";
//Your Domain name with URL path or IP address with path
const char* serverName = "https://********.azurewebsites.net/api/Measurements/";
unsigned long lastTime = 0;
// Set timer to 5 seconds (5000)
unsigned long timerDelay = 5000;
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("Connecting");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
Serial.println("Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading.");
}
void loop() {
//Send an HTTP POST request every 10 minutes
if ((millis() - lastTime) > timerDelay) {
//Check WiFi connection status
if(WiFi.status()== WL_CONNECTED)
{
std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
client->setInsecure();
HTTPClient https;
https.addHeader("Content-Type", "application/json"); // tried even "text/json"
//https.addHeader("Content-Length", "32");
https.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
https.addHeader("Host","******.azurewebsites.net");
https.addHeader("Cache-Control","no-cache");
String httpRequestData = "[{\"SensorId\": 1, \"Value\": 77.7}]";
if (https.begin(*client, serverName))
{
Serial.print("[HTTPS] POST...\n");
int httpCode = https.POST(httpRequestData);
if (httpCode > 0)
{
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTPS] POST... code: %d\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY)
{
String payload = https.getString();
Serial.println(payload);
}
else
{
Serial.printf("[HTTPS] POST... failed, error: %s\n", https.errorToString(httpCode).c_str());
}
}
else
{
Serial.printf("[HTTPS] POST... failed, error: %s\n", https.errorToString(httpCode).c_str());
}
https.end();
}
else
{
Serial.printf("[HTTPS] Unable to connect\n");
}
}
lastTime = millis();
}
}
Not receiving any error, just response code 415.
The HTTP 415 Unsupported Media Type client error response code indicates that the server refuses to accept the request because the payload
JSON text:
[{"SensorId": 1, "Value": 77.7}]
AppInsight:
PostMan successful request:
body of request in Postman:
And report from AppInsight:
App service:
Over PostMan I am able to reach azure and send data, but over Arduino I am not able to send data (I am able to get data, but not post)
Probably some beginner mistake.
Can someone give me hint?
Do I have wrong format of JSON?
im trying to send json parameter to asp request handler like this:
$scope.SaveCarUpgrades = function () {
var parameter = JSON.stringify(resultCarUpgrades);
$http.get("/ProfileEditor/saveUserCarUpgrades/" + $scope.useridCarUpgrades,
{ params: { name: parameter }}
).then(onsuccess, onfail);
function onsuccess(response) {
if (response.status == 200) {
$scope.saveUpgradesResult = "save upgrades success";
} else {
$scope.saveUpgradesResult = "save upgrades failed" + response.status;
}
}
function onfail(response) {
$scope.saveUpgradesResult = "save upgrades failed" + response.status;
// $scope.saveUpgradesResult = parameter;
}
}
c# request handler is something very simpe. its just for testing right now:
public string SaveUserCarUpgrades(string id)
{
string result = id;
var data = Request.QueryString["name"];
return id;
}
the problem is i always get 404 if if use json as parameter. (its a complex long json) but as simple json or simple string the response is fine. i dont think the problem is mime type as i set it in iis express in devcmd.
thank you for helping
An example code:
#include <FS.h> //this needs to be first, or it all crashes and burns...
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson
//define your default values here, if there are different values in config.json, they are overwritten.
char mqtt_server[40];
char mqtt_port[6] = "8080";
char blynk_token[34] = "YOUR_BLYNK_TOKEN";
//flag for saving data
bool shouldSaveConfig = false;
//callback notifying us of the need to save config
void saveConfigCallback () {
Serial.println("Should save config");
shouldSaveConfig = true;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println();
//clean FS, for testing
//SPIFFS.format();
//read configuration from FS json
Serial.println("mounting FS...");
if (SPIFFS.begin()) {
Serial.println("mounted file system");
if (SPIFFS.exists("/config.json")) {
//file exists, reading and loading
Serial.println("reading config file");
File configFile = SPIFFS.open("/config.json", "r");
if (configFile) {
Serial.println("opened config file");
size_t size = configFile.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());
json.printTo(Serial);
if (json.success()) {
Serial.println("\nparsed json");
strcpy(mqtt_server, json["mqtt_server"]);
strcpy(mqtt_port, json["mqtt_port"]);
strcpy(blynk_token, json["blynk_token"]);
} else {
Serial.println("failed to load json config");
}
}
}
} else {
Serial.println("failed to mount FS");
}
//end read
// The extra parameters to be configured (can be either global or just in the setup)
// After connecting, parameter.getValue() will get you the configured value
// id/name placeholder/prompt default length
WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
WiFiManagerParameter custom_mqtt_port("port", "mqtt port", mqtt_port, 5);
WiFiManagerParameter custom_blynk_token("blynk", "blynk token", blynk_token, 32);
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifiManager;
//set config save notify callback
wifiManager.setSaveConfigCallback(saveConfigCallback);
//set static ip
wifiManager.setSTAStaticIPConfig(IPAddress(10,0,1,99), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
//add all your parameters here
wifiManager.addParameter(&custom_mqtt_server);
wifiManager.addParameter(&custom_mqtt_port);
wifiManager.addParameter(&custom_blynk_token);
//reset settings - for testing
//wifiManager.resetSettings();
//set minimu quality of signal so it ignores AP's under that quality
//defaults to 8%
//wifiManager.setMinimumSignalQuality();
//sets timeout until configuration portal gets turned off
//useful to make it all retry or go to sleep
//in seconds
//wifiManager.setTimeout(120);
//fetches ssid and pass and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration
if (!wifiManager.autoConnect("AutoConnectAP", "password")) {
Serial.println("failed to connect and hit timeout");
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(5000);
}
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
//read updated parameters
strcpy(mqtt_server, custom_mqtt_server.getValue());
strcpy(mqtt_port, custom_mqtt_port.getValue());
strcpy(blynk_token, custom_blynk_token.getValue());
//save the custom parameters to FS
if (shouldSaveConfig) {
Serial.println("saving config");
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
json["mqtt_server"] = mqtt_server;
json["mqtt_port"] = mqtt_port;
json["blynk_token"] = blynk_token;
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("failed to open config file for writing");
}
json.printTo(Serial);
json.printTo(configFile);
configFile.close();
//end save
}
Serial.println("local ip");
Serial.println(WiFi.localIP());
}
void loop() {
// put your main code here, to run repeatedly:
}
I got this code from here (https://techtutorialsx.com/2017/01/08/esp8266-posting-json-data-to-a-flask-server-on-the-cloud/):
HTTPClient http; //Declare object of class HTTPClient
http.begin("http://anteph.pythonanywhere.com/postjson"); //Specify request destination
http.addHeader("Content-Type", "application/json"); //Specify content-type header
int httpCode = http.POST(JSONmessageBuffer); //Send the request
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
http.end(); //Close connection
But If I use:
int httpCode = http.POST(JSONmessageBuffer); //Send the request
This will send all the json data (i.e mqtt_server, mqtt_port, blynk_token). But I want to send only "blynk_token" and not the rest json data to server, So how can I achieve this?
Please suggest.
So to answer your question regarding "how to read and write limited Json data from SPIFF using DynamicJsonBuffer" you can take a look at your code right here where you read in the data.
if (configFile) {
Serial.println("opened config file");
size_t size = configFile.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());
json.printTo(Serial);
if (json.success()) {
Serial.println("\nparsed json");
strcpy(mqtt_server, json["mqtt_server"]); // copy mqtt_server value
strcpy(mqtt_port, json["mqtt_port"]); // copy mqtt_port value
strcpy(blynk_token, json["blynk_token"]); // copy blynk_token value
} else {
Serial.println("failed to load json config");
}
}
after this piece of code you have your 3 variables filled up with values.
These are mqtt_server, mqtt_port and blynk_token, which now contain the values read from the json which was saved in SPIFF.
If you then want to send the blynk_token to your local server you will have to put only that varialbe in your JSONmessageBuffer.
like so:
StaticJsonBuffer<300> JSONbuffer; //Declaring static JSON buffer
JsonObject& JSONencoder = JSONbuffer.createObject();
JSONencoder["blynk_token"] = blynk_token; // add blynk_token to the values sent to the server
char JSONmessageBuffer[300];
JSONencoder.prettyPrintTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));
Serial.println(JSONmessageBuffer);
HTTPClient http; //Declare object of class HTTPClient
http.begin("http://anteph.pythonanywhere.com/postjson"); //Specify request destination
http.addHeader("Content-Type", "application/json"); //Specify content-type header
int httpCode = http.POST(JSONmessageBuffer); //Send the request
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
http.end(); //Close connection
this line JSONencoder["blynk_token"] = blynk_token; is your way to go. Here you say which values you want to sent to your server.
This tutorial might also help you :)
I'm using android volley for send request to server side, in the other hand on server side I use php.
Here is my android code to receive response from server(does not matter what params is, because I do not need params on server side yet!):
JsonObjectRequest req = new JsonObjectRequest(URL, new JSONObject(params),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
Log.d("ATA d Response", response.toString());
VolleyLog.v("ATA Response:%n %s", response.toString(4));
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("ATA Response", " RESPONSE ERROR");
VolleyLog.e("Error: ", error.getMessage());
}
});
req.setShouldCache(false);
queue.getCache().clear();
queue.add(req);
Now, when in server side i return as response something like this:
if( isset($_POST)) {
echo json_encode(array("x"=>"y", "m"=>"n"));
exit();
}
every this is ok, and response is what server sends!
But! when in server side I return as response something like this:
if( isset($_POST)) {
echo json_encode(array(array("0"=>"1"),array("2"=>"3"),array("4"=>"5")));
exit();
}
Response is not ok and get this error:
06-17 02:28:53.456 D/Volley: [1296] BasicNetwork.logSlowRequests: HTTP response for request=<[ ] MY_URL 0xa64d9c1b NORMAL 1> [lifetime=3645], [size=60], [rc=200], [retryCount=0]
06-17 02:28:53.466 D/ATA Response: RESPONSE ERROR
06-17 02:28:53.466 E/Volley: [1] 2.onErrorResponse: Error:
What's wrong with my code?
Try sending a content type header. application/json should do the job.
header("Content-type:application/json");
send header before producing any outputs (i.e before echo statement).
Hello I have been using Spring 3 for my project, I have been stuck in on point.
if(ajax){
User user = userTemplate.getUser(form.getCreator_id());
int isPremium = user.getPremium();
if ( isPremium == 1 ){
Map<String,String> resultMap = new HashMap<String,String>();
response.setHeader("Access-Control-Allow-Headers", "*");
response.addHeader("Access-Control-Allow-Origin", "*");
resultMap.put("result", "success");
return new Gson().toJson(resultMap);
}else{
return "redirect:/f/redirectedUrl?url="+form.getWeb_page();
}
}
redirectedUrl controller is just for redirecting, but if the request is ajax request then i want to response the request as json.
How can I achieve this, thanks.
Edit : I can understand if request is ajax or not. My problem is if it is ajax i want to response json, if it is not then i want to redirect.
Use this code in your controller to identify if request is ajax or not and based on that you can add your logic.
boolean ajax = "XMLHttpRequest".equals(
getRequest().getHeader("X-Requested-With"));
You can decide it from header("X-Requested-With") of your httpRequest object.
public ModelAndView getDetails(HttpServletRequest request, HttpServletRespone response) {
if(ajax) {
try {
new MappingJacksonHttpMessageConverter().write(object, MediaType.APPLICATION_JSON, new ServletServerHttpResponse(response));
} catch(Exception e) {
logger.error("Error when converting to json");
}
return null;
} else {
return new ModelAndView("viewName");
}
}