I've been trying to send JSON data from arduino mega by using ESP8266 as a wifi shield, and I've used node.js as a socket server. The problem is it seems that a server didn't receive any data. here is my code
#include <ArduinoJson.h>
#include "SoftwareSerial.h"
String ssid ="ssid";
String password="pwd";
//SoftwareSerial esp(22,23);// RX, TX
String data;
String server = "server ip";
byte objlength;
String url = "";
String temp,hum,weight;
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
//String uri = "yourURI";
void reset() {
Serial2.println("AT+RST");
delay(1000);
if(Serial2.find("OK") ) Serial.println("Module Reset");
}
void connectWifi() {
String cmd = "AT+CWJAP=\"" +ssid+"\",\"" + password + "\"";
Serial2.println(cmd);
delay(4000);
if(Serial2.find("OK")) {
Serial.println("Connected!");
Serial2.println("AT+CIPSTATUS");
delay(300);
while(Serial2.available()){Serial.print(Serial2.read());}
}
else {
connectWifi();
Serial.println("Cannot connect to wifi"); }
}
void setup() {
delay(5000);
// put your setup code here, to run once:
Serial2.begin(115200);
Serial.begin(115200);
reset();
connectWifi();
}
void loop() {
temp = 25.60;
hum = 65.3;
weight = 65.3;
root["weight"] = weight;
root["light"] = temp;
root["humid"] = hum;
objlength = root.measureLength();
senddata();
delay(10000);
}
void senddata()
{
int objlength = root.measureLength();
Serial2.println("AT+CIPSTART=\"TCP\",\"" + server + "\",1336");//start a TCP connection.
delay(500);
if( Serial2.find("OK")) {
Serial.println("TCP connection ready");
}
else
{
Serial.println("can't establish TCP connection");
}
String sendCmd = "AT+CIPSEND=";//determine the number of caracters to be sent.
Serial2.println(sendCmd);
delay(200);
Serial2.println(objlength);
delay(500);
if(Serial2.find(">"))
{
Serial.println("Sending..");
root.printTo(Serial2);
root.printTo(Serial);
//Serial.println(postRequest);
delay(2000);
if( Serial2.find("SEND OK"))
{
Serial.println("Packet sent");
delay(200);
while (Serial2.available()) {
String tmpResp = Serial2.readString();
Serial.println(tmpResp);
}
// close the connection
}
//delay(1000);
Serial2.print("+++");
delay(1200);
Serial2.println("AT+CIPCLOSE");
delay(50);
Serial.println("Closed");
}
}
Here's my node.js
var net = require('net');
var server = net.createServer(function(socket){
socket.write('SEND OK');
//
socket.pipe(socket);
socket.on('data',function(data){
//if(typeof data != 'string'){
var jsontest = JSON.parse(data);
console.log('Received: ' + data);
console.log(jsontest.weight);
console.log(jsontest.light);
console.log(jsontest.humid);
//}
});
socket.on('listening',function(){
console.log(listen);
});
});
/*server.getConnections(function(err,count){
console.log(count);
});*/
server.listen(1336, '10.42.0.1');
I think that esp8266 can establish a connection with a server , but I don't know why the data won't show. Maybe it's about esp8266 respond time?
screenshot
As you can see from this screenshot, I run node.js server and arduino ,but data won't show on server side. Due to this,I'm not sure where are the problems that cause this.
I'm not an expert. I'm just learning how to do it but i'd say you are not giving enough time through connections. You are relying on delays rather than timeouts while waiting for a true response. There is a difference.
Add much more time or change your strategy by using serial.available() and read in a loop that last a prudential amount of time, and exit when you got data.
Sorry no pasting some code, but i hope you got the idea.
Also i'm facing a power problem. 3,3v pin in arduino uno could be weak in clone boards. But i dont think that's the case.
Related
I am using JScolor Picker from http://jscolor.com/examples/
Need Help to extract those R, G, B Values and use them as Integer input to variable in arduino code.
Please Guide me with code how can i get updated values of R, G & B Transferred via http back to arduino sketch.
I am using ESP8266 Webserver to host 2 Files
1) jscolor.js
2) index.html
Index.html code
<!DOCTYPE html>
<html>
<head>
<title>Getting colors</title>
</head>
<body>
<script src="jscolor.js"></script>
<div style="position:absolute; left:280px; top:10px;">
toHEXString = <span id="hex-str"></span><br />
toRGBString = <span id="rgb-str"></span><br />
R, G, B = <span id="rgb"></span><br />
H, S, V = <span id="hsv"></span>
</div>
<input class="jscolor {onFineChange:'update(this)'}" value="ffcc00">
<script>
function update(picker) {
document.getElementById('hex-str').innerHTML = picker.toHEXString();
document.getElementById('rgb-str').innerHTML = picker.toRGBString();
document.getElementById('rgb').innerHTML =
Math.round(picker.rgb[0]) + ', ' +
Math.round(picker.rgb[1]) + ', ' +
Math.round(picker.rgb[2]);
document.getElementById('hsv').innerHTML =
Math.round(picker.hsv[0]) + '°, ' +
Math.round(picker.hsv[1]) + '%, ' +
Math.round(picker.hsv[2]) + '%';
}
document.getElementById("picker_id").addEventListener('change', sendRGB);
// Added this to extract R, G, B Values but don't know how to handle it in arduino listner.
</script>
</body>
</html>
Arduino code (Sample code to host WebPage from ):
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266mDNS.h>
#include <ESP8266WebServer.h>
#include <FS.h> // Include the SPIFFS library
ESP8266WiFiMulti wifiMulti; // Create an instance of the ESP8266WiFiMulti class, called 'wifiMulti'
ESP8266WebServer server(80); // Create a webserver object that listens for HTTP request on port 80
File fsUploadFile; // a File object to temporarily store the received file
String getContentType(String filename); // convert the file extension to the MIME type
bool handleFileRead(String path); // send the right file to the client (if it exists)
void handleFileUpload(); // upload a new file to the SPIFFS
void setup() {
Serial.begin(115200); // Start the Serial communication to send messages to the computer
delay(10);
Serial.println('\n');
wifiMulti.addAP("itsveryeasy", "samepassword"); // add Wi-Fi networks you want to connect to
wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2");
wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3");
Serial.println("Connecting ...");
int i = 0;
while (wifiMulti.run() != WL_CONNECTED) { // Wait for the Wi-Fi to connect
delay(1000);
Serial.print(++i); Serial.print(' ');
}
Serial.println('\n');
Serial.print("Connected to ");
Serial.println(WiFi.SSID()); // Tell us what network we're connected to
Serial.print("IP address:\t");
Serial.println(WiFi.localIP()); // Send the IP address of the ESP8266 to the computer
if (!MDNS.begin("esp8266")) { // Start the mDNS responder for esp8266.local
Serial.println("Error setting up MDNS responder!");
}
Serial.println("mDNS responder started");
SPIFFS.begin(); // Start the SPI Flash Files System
server.on("/upload", HTTP_GET, []() { // if the client requests the upload page
if (!handleFileRead("/upload.html")) // send it if it exists
server.send(404, "text/plain", "404: Not Found"); // otherwise, respond with a 404 (Not Found) error
});
server.on("/upload", HTTP_POST, // if the client posts to the upload page
[](){ server.send(200); }, // Send status 200 (OK) to tell the client we are ready to receive
handleFileUpload // Receive and save the file
);
server.onNotFound([]() { // If the client requests any URI
if (!handleFileRead(server.uri())) // send it if it exists
server.send(404, "text/plain", "404: Not Found"); // otherwise, respond with a 404 (Not Found) error
});
server.begin(); // Actually start the server
Serial.println("HTTP server started");
}
void loop() {
server.handleClient();
}
String getContentType(String filename) { // convert the file extension to the MIME type
if (filename.endsWith(".html")) return "text/html";
else if (filename.endsWith(".css")) return "text/css";
else if (filename.endsWith(".js")) return "application/javascript";
else if (filename.endsWith(".ico")) return "image/x-icon";
else if (filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
bool handleFileRead(String path) { // send the right file to the client (if it exists)
Serial.println("handleFileRead: " + path);
if (path.endsWith("/")) path += "index.html"; // If a folder is requested, send the index file
String contentType = getContentType(path); // Get the MIME type
String pathWithGz = path + ".gz";
if (SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) { // If the file exists, either as a compressed archive, or normal
if (SPIFFS.exists(pathWithGz)) // If there's a compressed version available
path += ".gz"; // Use the compressed verion
File file = SPIFFS.open(path, "r"); // Open the file
size_t sent = server.streamFile(file, contentType); // Send it to the client
file.close(); // Close the file again
Serial.println(String("\tSent file: ") + path);
return true;
}
Serial.println(String("\tFile Not Found: ") + path); // If the file doesn't exist, return false
return false;
}
void handleFileUpload(){ // upload a new file to the SPIFFS
HTTPUpload& upload = server.upload();
if(upload.status == UPLOAD_FILE_START){
String filename = upload.filename;
if(!filename.startsWith("/")) filename = "/"+filename;
Serial.print("handleFileUpload Name: "); Serial.println(filename);
fsUploadFile = SPIFFS.open(filename, "w"); // Open the file for writing in SPIFFS (create if it doesn't exist)
filename = String();
} else if(upload.status == UPLOAD_FILE_WRITE){
if(fsUploadFile)
fsUploadFile.write(upload.buf, upload.currentSize); // Write the received bytes to the file
} else if(upload.status == UPLOAD_FILE_END){
if(fsUploadFile) { // If the file was successfully created
fsUploadFile.close(); // Close the file again
Serial.print("handleFileUpload Size: "); Serial.println(upload.totalSize);
server.sendHeader("Location","/success.html"); // Redirect the client to the success page
server.send(303);
} else {
server.send(500, "text/plain", "500: couldn't create file");
}
}
}
Personally, I use an Asynchronous Web server with the ESPAsyncWebServer library but I think you should be able to keep your current server and the code will still work :
First, in JavaScript, you just need to do a "POST" with jQuery :
function sendRGB() {
// Use values from the picker (it's just an exemple here)
var valueR;
var valueG;
var valueB;
$.post("receiveRGB", {
R: valueR,
G: valueG,
B: valueB
// You can add other variables if you want of course!
}
}
And for the Arduino :
void getRGB() {
String R = server.arg("R");
String G = server.arg("G");
String B = server.arg("B");
// Do what you want
server.send(204);
}
void setup() {
// init serial etc...
server.on("/receiveRGB", getRGB());
}
That code should work, tell me if it doesn't.
But I find that ESPAsyncWebServer is easier to use (javascript does not change) :
server.on("/receiveRGB", HTTP_POST, [](AsyncWebServerRequest *request) {
String R;
String G;
String B;
if(request->hasParam("R", true) && request->hasParam("G", true) && request->hasParam("B", true)) {
R = request->getParam("R", true)->value();
G = request->getParam("G", true)->value();
B = request->getParam("B", true)->value();
Serial.println(R + " " + G + " " + B);
}
request->send(204);
});
I'm trying to write an RCON Client in dart, but I'm getting stuck at this point:
The server recives the packet but seems like it cannot read it properly as reply I'm getting:
Rcon auth failed from rcon whitelist address 2.xxx.xxx.169:52672
Even tough the password is right:
"rcon_password" = "foo" ( def. "" ) - remote console password.
I've provided links to the valve's wiki within the code comments.
This is my code at the moment:
Socket socket;
int _id = 1;
const int SERVERDATA_AUTH = 3;
const int SERVERDATA_AUTH_RESPONSE = 2;
const int SERVERDATA_EXECCOMMAND = 2;
const int SERVERDATA_RESPONSE_VALUE = 0;
void main() async {
socket = await Socket.connect('hexah.net', 27015);
await socket.listen(onSocketData, onError: onError, onDone: onDone);
await _write(SERVERDATA_AUTH, 'foo');
}
void _write(int type, String body) async {
var bodyASCII = ascii.encode(body); //Get ASCII string with Null terminator
// Should I use this or the other way? ??
var size = bodyASCII.length + 14;
var buffer = new Int8List(size).buffer;
var bdata = new ByteData.view(buffer);
bdata.setInt32(0, size - 4, Endian.little); //Byte requests length (32bit le signed int).
bdata.setInt32(4, _id, Endian.little); //Any integer (32bit le signed int).
bdata.setInt32(8, type, Endian.little); //Valid values: SERVERDATA_* (32bit le signed int).
int writepos = 12;
await bodyASCII.forEach((element) {
bdata.setInt8(writepos, element);
writepos +=1;
});
bdata.setInt16(size-2, 0, Endian.little); //Write the null terminators
await socket.write(bdata);
_id++;
}
void onSocketData(var data){
print(data);
}
void onError(var data, StackTrace stack){
print(stack);
}
void onDone(){
print('Connection terminated');
}
Here is also a small example with nodejs:
var size = Buffer.byteLength(body) + 14,
buffer = new Buffer(size);
buffer.writeInt32LE(size - 4, 0);
buffer.writeInt32LE(id, 4);
buffer.writeInt32LE(type, 8);
buffer.write(body, 12, size - 2, "ascii");
buffer.writeInt16LE(0, size - 2);
Do you have any ideas?
especially about getting properly the lengths.
This is how the packet payload should be
Using a RawSocket I get this as reply:
RawSocketEvent.write
RawSocketEvent.readClosed
EDIT:
I'm seeing that the same packet sent from nodejs resulted in a successful authentication but Dart failes, any ideas why this is happening? (converting the packets from nodejs & dart to an array they resulted the same)
Solved!
The issue was that I had to use a RawSocket and write something like this:
var packet = bdata.buffer.asInt8List();
await socket.write(packet, 0, packet.length);
I am trying to do some network programming with a simple client and a server that is given to me. When my client gets connected to the server ,server prints message "Only one usage of each socket address (protocol/network address/port) is normally permitted"
The port that I am using is 6000 and localhost is the host.
I am using a Tcp client.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
namespace ConsoleTankClientVersion1
{
class Program
{
static void Main(string[] args)
{
TcpClient client = null;
NetworkStream netStream = null;
//server ip
String server = "127.0.0.1";
//server port
int servPort = 6000;
//The input string is converted to a stream of bytes
byte[] byteBuffer = Encoding.ASCII.GetBytes("JOIN#");
try
{
// Create socket that is connected to server on port 6000
client = new TcpClient(server, servPort);
Console.WriteLine("Connected to server... sending join string");
netStream = client.GetStream();
// Send the encoded string to the server
netStream.Write(byteBuffer, 0, byteBuffer.Length);
Console.WriteLine("Sent {0} bytes to server...", byteBuffer.Length);
int totalBytesRcvd = 0; // Total bytes received so far
int bytesRcvd = 0; // Bytes received in last read
// Receive the same string back from the server
while (totalBytesRcvd < byteBuffer.Length)
{
if ((bytesRcvd = netStream.Read(byteBuffer, totalBytesRcvd,
byteBuffer.Length - totalBytesRcvd)) == 0)
{
Console.WriteLine("Connection closed prematurely.");
break;
}
totalBytesRcvd += bytesRcvd;
}
Console.WriteLine("Received {0} bytes from server: {1}", totalBytesRcvd,
Encoding.ASCII.GetString(byteBuffer, 0, totalBytesRcvd));
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
TcpTimedWaitDelay is 30 s
Max user port value is 60000
Response of QNetworkReply::readAll is empty when QNetworkReply::error() != NoError.
Is this normal?
I've a Node+Express server that always send a detailed description in case of http status different of 200; I cant get this description from my Qt client base on QNAM. Qt version is 5.3, OS Win 7 64b.
This is my code, really I don't think this can help.
PendingRequest *Foo::sendMsg(QStandardItem *requestItem, HTTP_METHOD_ID method, QString path)
{
PendingRequest *pReq = new PendingRequest(method);
QString url = QString("https://%1:%2%3").arg(host, QString::number(port), path);
QNetworkRequest qNetReq = QNetworkRequest(QUrl(url));
//set headears
qNetReq.setHeader(QNetworkRequest::KnownHeaders::UserAgentHeader, HttpUserAgent);
qNetReq.setRawHeader("Connection", "Keep-Alive");
if(!credentials.isEmpty())
{
qNetReq.setRawHeader("Authorization", QByteArray("Basic ")+credentials);
}
if(!sessionId.isEmpty())
{
qNetReq.setRawHeader("Session-Id", sessionId);
}
//send request
QNetworkReply *reply;
if(method == HTTP_METHOD_ID::POST)
{
qNetReq.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
QByteArray data = outHandlerList[outHandlerIndex](requestItem);
reply = netManager.post(qNetReq, data);
}
else
{
reply = netManager.get(qNetReq);
}
connect(reply, SIGNAL(finished()), this, SLOT(handleResponse()));
connect(reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(handleSslErrors(QList<QSslError>)));
return pReq;
}
and this where I handle response:
void Foo::handleResponse()
{
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
if(reply->hasRawHeader("Session-Id"))
sessionId = reply->rawHeader("Session-Id");
PendingRequest *pReq = pendingRequestMap.contains(reply) ? pendingRequestMap.take(reply) : 0;
Q_ASSERT(pReq);
QStandardItem *responseItem = 0;
QString error;
if(reply->error() != QNetworkReply::NoError)
{
qDebug() << "readAll: ", reply->readAll(), "error: ", reply->errorString();
error = reply->errorString();
}
else
{
responseItem = inHandlerList[pReq->inHandlerIndex](reply, error, pReq);
}
reply->deleteLater();
}
Thanks a lot for your help.
From the documentation:
QByteArray QIODevice::readAll()
This is an overloaded function.
Reads all available data from the device, and returns it as a
QByteArray.
This function has no way of reporting errors; returning an empty
QByteArray() can mean either that no data was currently available for
reading, or that an error occurred.
I had the same problem, spent hours debugging and searching online for solutions...
The resolution is to connect QIODevice::readyRead to as per the documentation:
connect(reply, &QIODevice::readyRead, this, [=]() {
QByteArray response = reply->readAll();
qDebug() << response;
});
You now have the server reply regardless of the HTTP error code.
I'm currently experimenting with sending a string to my Arduino Yun and trying to get it to reply back depending on what I send it.
I picked up a framework of some code here and have been experimenting with it but apart from the serial monitor displaying 'ready' I can't make it go any further.
The code is:
//declace a String to hold what we're inputting
String incomingString;
void setup() {
//initialise Serial communication on 9600 baud
Serial.begin(9600);
while(!Serial);
//delay(4000);
Serial.println("Ready!");
// The incoming String built up one byte at a time.
incomingString = "";
}
void loop () {
// Check if there's incoming serial data.
if (Serial.available() > 0) {
// Read a byte from the serial buffer.
char incomingByte = (char)Serial.read();
incomingString += incomingByte;
// Checks for null termination of the string.
if (incomingByte == '\0') {
// ...do something with String...
if(incomingString == "hello") {
Serial.println("Hello World!");
}
incomingString = "";
}
}
}
Can anyone point me in the right direction?
Thanks
I suspect the problem is that you're adding the null terminator onto the end of your string when you do: incomingString += incomingByte. When you're working with string objects (as opposed to raw char * strings) you don't need to do that. The object will take care of termination on its own.
The result is that your if condition is effectively doing this: if ("hello\0" == "hello") .... Obviously they're not equal, so the condition always fails.
I believe the solution is just to make sure you don't append the byte if it's null.
Try This:
String IncomingData = "";
String Temp = "";
char = var;
void setup()
{
Serial.begin(9600);
//you dont have to use it but if you want
// if(Serial)
{
Serial.println("Ready");
}
//or
while(!Serial)
{delay(5);}
Serial.println("Ready");
void loop()
{
while(Serial.available())
{
var = Serial.read();
Temp = String(var);
IncomingData+= Temp;
//or
IncomingData.concat(Temp);
// you can try
IncomindData += String(var);
}
Serial.println(IncomingData);
IncomingData = "";
}