Telegrambot with arduino ethernet 301 Moved Permanently response - arduino

I am trying to make my arduino mega bot for notifications and i stumbled upon a problem.
I have no idea when this error code apears - is it possible that the problem is not with code but with bot side? I got token for my bot, I created a chat and made chat publicly available
#include <EtherCard.h>
const char apihost[] PROGMEM = "api.telegram.org";
const char botToken[] PROGMEM = "1111111111:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
const char chatId[] PROGMEM = "1234567890";
static byte mymac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x31 };
byte Ethernet::buffer[900];
Stash stash;
static byte session;
static void sendTelegramMessage () {
byte sd = stash.create();
stash.print("chat_id=");
stash.print(chatId);
stash.print("&text=");
stash.print("Hello from EtherCard!");
stash.save();
int stash_size = stash.size();
// Compose the http POST request, taking the headers below and appending
// previously created stash in the sd holder.
Stash::prepare(PSTR("POST /bot$S/sendMessage HTTP/1.1" "\r\n"
"Host: $F" "\r\n"
"Content-Length: $D" "\r\n"
"Content-Type: application/x-www-form-urlencoded" "\r\n"
"\r\n"
"$H"),
botToken, apihost, stash_size, sd);
// send the packet - this also releases all stash buffers once done
// Save the session ID so we can watch for it in the main loop.
session = ether.tcpSend();
}
void setup () {
Serial.begin(57600);
Serial.println("\nStarting Telegram Bot Example");
// Change 'SS' to your Slave Select pin, if you arn't using the default pin
if (ether.begin(sizeof Ethernet::buffer, mymac, SS) == 0)
Serial.println(F("Failed to access Ethernet controller"));
if (!ether.dhcpSetup())
Serial.println(F("DHCP failed"));
ether.printIp("IP: ", ether.myip);
ether.printIp("GW: ", ether.gwip);
ether.printIp("DNS: ", ether.dnsip);
if (!ether.dnsLookup(apihost))
Serial.println(F("DNS lookup failed for the apihost"));
ether.printIp("SRV: ", ether.hisip);
sendTelegramMessage();
}
void loop () {
ether.packetLoop(ether.packetReceive());
const char* reply = ether.tcpReply(session);
if (reply != 0) {
Serial.println("Got a response!");
Serial.println(reply);
}
}
Everything seems to work well but I get response in serial like this:
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
Any ideas what i did wrong?

Related

Why Node-red Debug node doesn't show my mqtt message?

I'm trying to send data from my Wemos to Node-red via MQTT. I created a nested object I want to send to MQTT. From the serial of Arduino IDE the output is this (and that's what I want):
[{"AcX":-1,"AcY":-1,"AcZ":-1},{"AcX":-1,"AcY":-1,"AcZ":-1},{"AcX":-1,"AcY":-1,"AcZ":-1},{"AcX":-1,"AcY":-1,"AcZ":-1},{"AcX":-1,"AcY":-1,"AcZ":-1}]
It seems all correct but the debug node show nothing. what am I missing?
Here's the code:
//LIBRARY
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#include <PubSubClient.h>
#include<Wire.h>
//JSON Array and mqtt data
#include <ArduinoJson.h>
#define MQTT_BUFFER 512
//MPU
const int MPU = 0x68; // I2C address of the MPU-6050
int16_t AcX, AcY, AcZ;
// IP adress Raspberry Pi
const char* mqttServer = "raspi-hyperink";
const int mqttPort = 1883;
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
//MPU
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
//SERIAL
Serial.begin(115200);
// WiFiManager
// Local intialization.
WiFiManager wifiManager;
// Uncomment and run it once, if you want to erase all the stored information
//wifiManager.resetSettings();
// set custom ip for portal
//wifiManager.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
// fetches ssid and pass from eeprom 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
wifiManager.autoConnect("AutoConnectAP");
// if you get here you have connected to the WiFi
Serial.println("Connected.");
//server.begin();
//CLIENT
client.setServer(mqttServer, mqttPort);
client.setCallback(callback);
server.begin();
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived in topic: ");
Serial.println(topic);
Serial.print("Message:");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
Serial.println("-----------------------");
}
//RECONNECT FUNCTION
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("esp8266")) {
Serial.println("connected");
// Once connected, publish an announcement...
//client.publish("outTopic", "hello world");
// ... and resubscribe
//client.subscribe("inTopic");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void loop(){
WiFiClient(espClient) = server.available(); // Listen for incoming clients
if (espClient) { // If a new client connects,
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (espClient.connected()) { // loop while the client's connected
if (espClient.available()) { // if there's bytes to read from the client,
char c = espClient.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// Display the HTML web page
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// Web Page Heading
client.println("<body><h1>ESP8266 Web Server</h1>");
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline, then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
espClient.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
if (!client.connected()) {
reconnect();
}
client.loop();
//compute the required size
const size_t CAPACITY = JSON_ARRAY_SIZE(5) + 5*JSON_OBJECT_SIZE(3);
//allocate the memory for the document
StaticJsonDocument<CAPACITY> doc;
//Create an empty array
JsonArray arr = doc.to<JsonArray>();
//definiamo quanti campioni registrare prima di inviarli tramite mqtt
for (int i=0; i<5; i++){
//MPU reading
Wire.beginTransmission(MPU);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU, 14, true); // request a total of 14 registers
AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
//Create JSON Array
JsonObject obj = doc.createNestedObject();
obj["AcX"] = AcX;
obj["AcY"] = AcY;
obj["AcZ"] = AcZ;
delay(3000);
}
//MQTT PUBLISHING JSON PACKAGE
char mqttData[MQTT_BUFFER];
serializeJson(doc, mqttData);
Serial.println(mqttData);
client.publish("esp8266", mqttData);
//client.subscribe("esp8266");
client.subscribe("esp8266");
delay(10000);
//Inserire un ciclo WHILE dove
//mentre il wifi è connesso invia i dati all'mqtt
//altrimenti li salva e basta
}
This is the mqtt node
Node-red debug
Normally debug should show you what you are publishing to your MQTT broker. As simple troubleshooting I would start moving backwards:
Replace the NodeRED client by any other one. Is the problem still there? Very likely it will be meaning that the problem is not on the MQTT client.
So we move a step "backwards"
Replace the MQTT Broker, use another one from the internet, one that you know works fine. The problem, is it still there? If it's not there, voilà, you found the problem (the broker), if it's still there, it means that the issue is on client publishing your msgs. It might be the msg itself.
So we move a step "backwards"
Replace you msg by another one, much simpler. Does it work ?
You get the idea :)

WiFiClientSecure readString function slow

I have a sketch that requests a device token from Facebook in order to authenticate a Wemos D1 Mini.
All in all, I want to reproduce the following, which gives me a device code in less than a second:
curl https://graph.facebook.com/v2.7/device/login -d
"type=device_code&access_token=MYTOKEN"
I set up the following sketch which works albeit very slowly. It fetches the device token in about 17 seconds.
It seems that String response = client.readString(); is the culprit.
Can any offer advice on why that could be, and how to possibly remedy it?
Thank you kindly,
Nate
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <ArduinoHttpClient.h>
#include <ArduinoJson.h>
WiFiClientSecure client; //edited
void setup() {
connect(WIFI_SSID, WIFI_PWD); //edited
Serial.println(getFBDeviceToken());
}
void connect(const char* WIFI_SSID, const char* WIFI_PWD) {
delay(1000);
WiFi.persistent(false);
delay(1000);
WiFi.mode(WIFI_STA);
if (WiFi.status() == WL_DISCONNECTED) {
WiFi.begin(WIFI_SSID, WIFI_PWD);
while(WiFi.status() != WL_CONNECTED){
delay(1000);
Serial.println("connecting...");
}
Serial.println("\r\n"+WiFi.localIP());
}
}
String getFBDeviceToken(){
//Connect to FB SSL
if(!client.connect(host, httpPort)){
return "** Failed to connect **";
}
client.println("POST " + path + " HTTP/1.1");
client.println("Host: " + String(host));
client.println("User-Agent: ESP8266/1.0");
client.println("Connection: close");
client.println("Content-Type: application/x-www-form-urlencoded;");
client.print("Content-Length: ");
client.println(data.length());
client.println();
client.println(data);
String response = client.readString();
int bodypos = response.indexOf("\r\n\r\n") + 4;
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(response.substring(bodypos));
String device_token = root[String("user_code")];
return device_token;
}
I am not sure if this is still relevant for you but I faced the same situation and I believe I found a solution. If it is not relevant to you, perhaps it will help some other, especially given that the default WiFiClientSecure library will soon be switched to BearSSL and no support is currently being given for the existing implementation.
Although I did not manage to speed up readString function, I used the WiFiClientSecure::read(uint8_t *buf, size_t size) function to get the data from the server:
// Buffer size, 128 bytes in this case
#define RESP_BUFFER_LENGTH 128
// Pointer to actual buffer
uint8_t * _buffer = new uint8_t[RESP_BUFFER_LENGTH];
// String to hold the final response
String _responseString = "";
// If info is still available
while (wifiClient.available())
{
// Fill the buffer and make a note of the total read length
int actualLength = wifiClient.read(_buffer, RESP_BUFFER_LENGTH);
// If it fails for whatever reason
if(actualLength <= 0)
{
// Handle as you see fit
return -1;
}
// Concatenate the buffer content to the final response string
// I used an arduino String for convenience
// but you can use strcat or whatever you see fit
_responseString += String((char*)_buffer).substring(0, actualLength);
}
// Clear buffer memory
delete[] _buffer;
I don't know why the regular readString() is so slow, but this method is considerably faster, with my relatively small messages (~50 bytes) the response is being read almost instantly.
If look under hood, readString() always reads all data and when it reads the last symbol it stucks with server communication.
To avoid it you should not read last one symbol somehow.
I read headers by using readStringUntil('\n') and searching Content-Length header.
When headers has been read, just use readBytes with content-length.
HTTP request now took around 150ms.

Arduino & Ethernet module ether.tcpSend Cannot store data to database (via PHP GET Request)

i want to send data from my Arduino to database by PHP (using GET request)
i have tested my PHP and the data successfuly stored in database
but when i wan to implement to my arduino, the data not store to database
im using:
- Arduino UNO
- Ethernet Module ENC28J60
- Ip Address DHCP (Success get ip)
This is my arduino code
#include <SPI.h>
#include <EtherCard.h>
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
#define PATH "/bonbit/firebaseTest.php"
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
int totalCount = 1;
const char website[] PROGMEM = "maballo.net";
byte Ethernet::buffer[700];
uint32_t timer;
Stash stash;
void setup() {
Serial.begin(9600);
Serial.println("\n[getDHCPandDNS]");
if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
Serial.println( "Failed to access Ethernet controller");
if (!ether.dhcpSetup())
Serial.println("DHCP failed");
ether.printIp("My IP: ", ether.myip);
// ether.printIp("Netmask: ", ether.mymask);
ether.printIp("GW IP: ", ether.gwip);
ether.printIp("DNS IP: ", ether.dnsip);
delay(2000);
Serial.println(F("Ready"));
}
void loop()
{
Serial.println("Sending Data..");
ether.packetLoop(ether.packetReceive());
if (millis() > timer) {
timer = millis() + 10000;
byte sd = stash.create();
stash.print("arduino_data=");
stash.print(totalCount);
stash.save();
// generate the header with payload - note that the stash size is used,
// and that a "stash descriptor" is passed in as argument using "$H"
Stash::prepare(PSTR("GET http://$F/$F.csv HTTP/1.0" "\r\n"
"Host: $F" "\r\n"
"Content-Length: $D" "\r\n"
"\r\n"
"$H"),
website, PSTR(PATH), website, stash.size(), sd);
// send the packet - this also releases all stash buffers once done
ether.tcpSend();
}
totalCount++;
delay(3000);
}

enc28j60 with arduino and local web service

please help
i am trying to use arduino Pro mini with ENC28j60 to get data from my local web service
the URL i used to get the data is (http://192.168.1.5:801/m/Service1.asmx/HelloWorld?tag=01)
when i use this URL in browser it return this result
peter danile,1234567
with arduino
i use this code but i can't get a result
// Demo using DHCP and DNS to perform a web client request.
// 2011-06-08 <jc#wippler.nl> http://opensource.org/licenses/mit-license.php
#include <EtherCard.h>
// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
byte Ethernet::buffer[700];
static uint32_t timer;
const char website[] PROGMEM = "192.168.1.5";
//char website[] PROGMEM = "google.com";
// called when the client request is complete
static void my_callback (byte status, word off, word len) {
Serial.println(">>>");
Ethernet::buffer[off+300] = 0;
Serial.print((const char*) Ethernet::buffer + off);
Serial.println("...");
}
void setup () {
Serial.begin(57600);
Serial.println("\n[webClient]");
if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
Serial.println( "Failed to access Ethernet controller");
if (!ether.dhcpSetup())
Serial.println("DHCP failed");
ether.printIp("IP: ", ether.myip);
ether.printIp("GW: ", ether.gwip);
ether.printIp("DNS: ", ether.dnsip);
if (!ether.dnsLookup(website))
Serial.println("DNS failed");
ether.printIp("SRV: ", ether.hisip);
}
void loop () {
ether.packetLoop(ether.packetReceive());
if (millis() > timer) {
timer = millis() + 5000;
Serial.println();
Serial.println(PSTR("/m/Service1.asmx/HelloWorld?"));
Serial.print("<<< REQ ");
ether.hisport = 801;//to access local host
ether.browseUrl(PSTR("/m/Service1.asmx/HelloWorld?"), "tag=01", website, my_callback);
}
}

ethernet webserver example, client.stop causes lag time issues

Using the ethernet WebServer example code, I've got my arduino to host a website stored on an SD card. The website uses jquery to post the position of the mouse in the webbrowser back to the arduino. I would ultimately like to use this info to control a servo motor, however, the problem I have is that the client.stop line in each iteration of the void loop causes a large lag time in between when the mouse moves and when the arduino gets the information.
Is there a way to make this code only use the execute the stop.client line when the mouse stops moving. So effectively when there no information being sent from the to the arduino via the post method?
Here is my code.
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
String POST = "";
int count = 0;
const int chipSelect = 4;
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,178,30);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
EthernetClient client;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
Serial.setTimeout(10);
//start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
client.setTimeout(1);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
//SD card stuff
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
String POST = "";
while(client.available()){
c = client.read();
// save the variables somewhere
POST += c;
}
if(POST != ""){
Serial.println(POST);
}
//load html/css/js for website only once
if (count <= 0){
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
//client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
File dataFile = SD.open("site.txt");
// if the file is available, write to it:
if (dataFile) {
while (dataFile.available()) {
//Serial.write(dataFile.read());
client.write(dataFile.read());
}
dataFile.close();
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening site.txt");
}
}
//count = 1;
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
if (count == 0){
delay(500);
}
else{
delay(1);
}
count=1;
// close the connection:
client.stop();
Serial.println("client disonnected");
}
}
yes, is possible but realy hard as you have to implement HTTP\1.1, also this will reamin slow as for every mouse position, browser have to send a full HTTP request, arduino read and intepretate it.
Best solution is to use websocket (there are already some serbsocket server lybrary for arduino), once a websocket is setted-up, you have a two way communication exactly like a Serial!

Resources