luc-github / ESP3D

FW for ESP8266/ESP8285/ESP32 used with 3D printer
GNU General Public License v3.0
1.73k stars 465 forks source link

[FEATURE REQUEST] HTTP requests for home automation control #524

Closed jojolll closed 3 years ago

jojolll commented 3 years ago

Is your feature request related to a problem? Please describe. Not a problem, but here's the context: I want to drive my 3D printer with a cheap 433MHz plug. I have a home automation system similar to Jeedom which controls about ten of these plugs, via a RFLINK gateway.

Describe the solution you'd like Controlling a home automation system from a HTTP request is very simple, and this is what I wanted to add to ESP3D to simply turn off my 433MHz plug at the end of printing. To do this, I didn't find anything in the current release. So I added in the Arduino code command.cpp a new custom command case.

Describe alternatives you've considered I didn't find any simple alternative to control my home automation, then knowing that the ESP is connected to the home network it would be stupid to do without a simple request.

Here is the solution that I set up in command.cpp (as a beginner coder I specify, I have no pretension to say that it is optimized it is simply functional and it meets my need) :

Before the originals #include

#include <ESP8266HTTPClient.h> // PERSONNAL MOD
HTTPClient http;

after #endif and before case 700:

    //HTTP Custom request [ESP666] URL=<url>
    case 666:
        parameter = get_param (cmd_params, "URL=", true);
        if (parameter.length() == 0) {
            ESPCOM::println ("Faut entrer une URL banane", output, espresponse);
            return false;
        }
        http.begin(parameter);
        http.GET();
        http.end();

        break;

I can now add to my gcode this command in order to launch a GET request: M118 P0 [ESP666] URL=http://domotic-ip:8080/devicetype/4/exec?token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxf&value=0 and this is turning off my plug 👍 We can then imagine an infinite number of scenarios EDIT : I changed my scenario, now I intend to inform my home automation at the beginning of printing so that it blocks the wifi on if I go to bed, and at the end of printing to turn it off then, and also turn off the plug a few seconds later.

I haven't received my printer yet the only tests I've done are in serial, but it must be the same ;)

The only "problem" encountered is the disappearance of the end of the message after the "&" character in the link when I enter the order via the ESP3D web interface. I have no idea why, but when I enter this character it considers the command as finished, so everything else after this character is ignored. I was unable to identify the source of the problem.

This problem does not exist when using the serial console to send the command. Knowing that this is the protocol that the printer will use, it is fine with me.

github-actions[bot] commented 3 years ago

Thank your for submiting, please be sure you followed template or your issue may be dismissed. if you deleted the template it is here

luc-github commented 3 years ago

WebUI macro allows to use such URL command ( enfin sans la banane ^_^) but indeed there is no such mechanism for gcode

About web command this is due to fact that the command is encoded but because it is seens as valid url the & is not encoded and so become part of ESP web command - it may be fixed by forcing the & encoding I had to do for another char like this - I need to check - you can try by changing & with %26 to see if it solve the problem

Adding a new [ESPXXX] command for this could be a good idea - using notification command

jojolll commented 3 years ago

I finally received my printer and was able to test my protocol: it didn't work! 💯

There's a problem I didn't have in mind with Marlin, every ":" in the URL makes it think it's a command, so it doesn't reach ESP3D in one "sentence". So I changed my code, to make 3 parameters (IP, PORT and PATH) to create a concatenated URL with http://... before sending the GET request.

Again it didn't work, I have the impression that despite serial communication, either marlin or esp3D don't like "&" and delete the end of the URL. I haven't been able to see where it comes from so for now I hardcoded my URL into the esp3D code. It's beautiful, I know 👍 👍

luc-github commented 3 years ago

did you changed the & by %26 ?

jojolll commented 3 years ago

did you changed the & by %26 ? Not tried directly in the gcode. I try as soon as I finish my print

jojolll commented 3 years ago

Didn't work either, exactly the same error :(

luc-github commented 3 years ago

Ok I think the easiest solution is to use encoded64 URL so url : https://github.com/luc-github/ESP3D/issues/524 using a simple encoder https://www.base64encode.org/ will give : aHR0cHM6Ly9naXRodWIuY29tL2x1Yy1naXRodWIvRVNQM0QvaXNzdWVzLzUyNA==

it should avoid any char conflict

so the command would be [ESP620] URL=aHR0cHM6Ly9naXRodWIuY29tL2x1Yy1naXRodWIvRVNQM0QvaXNzdWVzLzUyNA==

I will work on this today - seems decode64 is not same between esp32 and esp8266

jojolll commented 3 years ago

aHR0cHM6Ly9naXRodWIuY29tL2x1Yy1naXRodWIvRVNQM0QvaXNzdWVzLzUyNA==

Hello ! Since I don't really have any coding basics, it didn't occur to me to decode the URL from ESP, but your message made me think.

At the beginning I looked in base64 but indeed it's a mess between Esp32 and 8266. in addition you have to use character tables for existing libraries and I don't like that x)

Looking at the encoding formats there is simply the "URL encode", which I think was your original idea but I hadn't tried to decode it on the esp side, that's why it didn't work.

So I'm correcting the situation, what do you think about something like that:

//HTTP Custom request [ESP666] URL=<Encoded URL, ex: "URL=https%3A%2F%2Fgithub.com%2Fluc-github%2FESP3D%2Fissues%2F524">
    case 666:
        parameter = get_param (cmd_params, "URL=");
        if (!parameter.length()) {
            ESPCOM::println ("Faut entrer une URL banane", output, espresponse);
            return false;
        }
        request = urldecode(parameter);
        ESPCOM::println (request, output, espresponse);
        http.begin(request);
        result = "";
        while (result != "200" && tries < 5){
        result = http.GET();
        ESPCOM::println (result, output, espresponse);
        tries++;
        }
        tries = 0;
        http.end();
        break;

functions etc. :


#include <ESP8266HTTPClient.h> // PERSONNAL MOD
HTTPClient http;
String request,result;
int tries;
unsigned char h2int(char c)
{
    if (c >= '0' && c <='9'){
        return((unsigned char)c - '0');
    }
    if (c >= 'a' && c <='f'){
        return((unsigned char)c - 'a' + 10);
    }
    if (c >= 'A' && c <='F'){
        return((unsigned char)c - 'A' + 10);
    }
    return(0);
}

String urldecode(String str)
{

    String encodedString="";
    char c;
    char code0;
    char code1;
    for (int i =0; i < str.length(); i++){
        c=str.charAt(i);
      if (c == '+'){
        encodedString+=' ';  
      }else if (c == '%') {
        i++;
        code0=str.charAt(i);
        i++;
        code1=str.charAt(i);
        c = (h2int(code0) << 4) | h2int(code1);
        encodedString+=c;
      } else{
        encodedString+=c;  
      }
      yield();
    }
   return encodedString;
}

knowing that two things must be taken care of:

EDIT : I confirm that from the WEB interface this technique works. I need to test from the SD card as soon as I finish my print.

luc-github commented 3 years ago

well I suggested to use encode64 because it do not use any special char like % , also this does not need any change in webUI

so what I did : I do not have any server so I used the jigsaw url, one from HTTPClient sample code image I have enabled the debug to see the decoded and the http code So from PIO:

image

so with debug off image

and from WebUI image

Currently https is not supported and I cannot test in real case - so feel free to check - the latest version is 3.0.0.75

luc-github commented 3 years ago

@jojolll may I know what is your configuration: Printer board and ESP Board ?

jojolll commented 3 years ago

@luc-github Sure, Ender 3 V2 with Creality 4.2.2 board (STM32 + silent TMC2208). For ESP3D, an ESP8266 (Wemos D1 mini) with DTH22 sensor.

I think it doesn't change anything but I preferred to connect directly to the TX and RX of the card's USB-SERIE module rather than to the isolated (and smaller) vias on the back : image

luc-github commented 3 years ago

Thank you ^_^

luc-github commented 3 years ago

@jojolll did you had chance to test the feature ? is it working ? can we close the issue ?

jojolll commented 3 years ago

@jojolll did you had chance to test the feature ? is it working ? can we close the issue ?

I tested both techniques, mine on ESP3D v2 works in all cases from the WEB interface. On the other hand from the SD card, my URL is too long and ESP3D has only the first ~90 characters approximately... I didn't look further, and think that it's Marlin that truncates the M118 too long (even if I didn't find any info on it).

On the V3, exactly the same fight. Once the URL has been encoded in base64, everything works for the best from the interface.

On the other hand I have an error when I boot from the SD card, but I couldn't find out where it comes from. I tried with a shorter URL, but the result is the same: [ESP620] URL=aHR0cDovL2h0dHBiaW4ub3JnL2dldA== -> works in the interface but not from the SD card.

image

luc-github commented 3 years ago

Check if you can send this command from serial to ESP board if yes may be Marlin does not allow long command ?

luc-github commented 3 years ago

in that case you may use macro

[ESP700]/notification.cmd

in SD gcode file where /notification.cmd file on esp3D FS has the long command

jojolll commented 3 years ago

Sorry I lost time doing the tests directly from my functional ESP... Finally I should have started by doing a config on a blank ESP.

Finally when I place my command directly on the serial port, it works. So Marlin must unfortunately have a character limitation :( I can't see how to get around that.

image

luc-github commented 3 years ago

then use the solution I gave you: use M118 [ESP700]/notif.cmd instead and upload a file /notif.cmd on ESP3D filesystem which contain the command [ESP620]URL=XXXXXXX

It should workaround the command line size

luc-github commented 3 years ago

I guess issue can be closed

github-actions[bot] commented 3 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.