luc-github / ESP3D

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

[FEATURE REQUEST]🦄Notification using custom webhook #726

Open luc-github opened 2 years ago

luc-github commented 2 years ago

as suggested by @cyberiano https://github.com/luc-github/ESP3D/pull/708#issuecomment-1047456970

the issue is to fit all data in 3 slots : (not including message content) Token 1 = 63 chars (hidden in settings) Token 2 = 63 chars (hidden in settings) Token extra = 128 chars fully visible

also what the AUTO_NOTIFICATION behaviour should do with such notification ? should be disabled ? or need to change the content of

define NOTIFICATION_ESP_ONLINE "Hi, %ESP_NAME% is now online at %ESP_IP%"

which mean the webhook is actually hardcoded which I would like to avoid as much as possible

Another possibility would be to allow more variables in message and also use [ESP600] to define id and value like [ESP600]ID=msg MSG=Hi, %ESP_NAME% is now online at %ESP_IP% another possibility would be to allow template message file on FS and use it if present

cyberiano commented 2 years ago

Thanks Luc!

Sounds promising.

I don't know (yet) how ESP3D manage notifications and how this feature is coded.

The main use case for this feature request is to integrate ESP3D notifications with customs apps like home automation software (Home Assistant in my case) and notify the status of the printer via webhook. For example, when printer start printing, stops or got some error. This allows make some automations you need according the printer status changes.

The idea of a payload template is really good because most of the webhooks are expecting json object as payload.

This is an example of Home Assistant webhook request:

curl -X POST -d '{ "key": "value" }' https://your-home-assistant:8123/api/webhook/some_hook_id

You actually can do this with Octoprint on the Raspberry Pi but if this feature can be ported to ESP3D will be awesome!

The price of a Raspberry Pi doesn't worth the purpose.

luc-github commented 2 years ago

about automation there is a big difference between raspberry and esp3d 1 - Raspberry is streaming GCODE so it is always On when printing 2 - ESP3D is a command bridge and server WebUI so WebUI is not always On and just react to [ESP600] messages,

So the ESP3D current autonotification is limited to ESP3D got internet access , as it do not monitor printing error and may even not able to catch them alone that is why I suggest to put [ESP600] notifications in GCODE file, they will be processed by ESP3D when it see them.

I understood the format so I can imagine this way to setup

T1= some_hook_id T= https://your-home-assistant:8123/api/webhook/$ID [ESP600]ID=key MSG=value

because it is custom web hook it will use template (but I am also considering using autonotification template for all notifications if available to allow user to change it anytime) 1 - autonotification template "{"enable": "true"}" 2 - message payload template "{"$ID":"$MSG"}" $ID and $MSG will be replaced by values provided by [ESP600]

Just an idea for the moment to store and feed data

cyberiano commented 2 years ago

Thanks for the explanation, now I understand how it works.

Putting the [ESP600] codes on the .GCODE file you can actually notify the start and finish, not the errors. But it's OK!

About the T1, I think it is not necessary to put a variable for the hook id separated to the URL, this is the Home Assistant way to implement webhooks, and this webhook feature needs to be generic.

With just one field to config the full webhook URL it's OK and will be more generic for other type of webhook integrations.

Also, to be more flexible, instead of the hook id variable, it's more important to have a method configuration for the request, I mean, GET, POST, PUT, DELETE, and if there is another token available will be awesome to send custom request headers, for example: "Content-Type: application/json"

The payload template is perfect.

luc-github commented 2 years ago

the idea behind using T1 it is because T has only 127 chars so I am afraid it is not enough that saif if need to add header and method it won't fit for sure so better add all to template and use $T1 $T2 $T $KEY $MSG as variables in template

luc-github commented 2 years ago

@cyberiano As I rewriting all command syntax I just remember this command : https://github.com/luc-github/ESP3D/blob/3.0/esp3d/src/core/espcmd/ESP620.cpp it was originally done to control remote device but I guess it could also be used for the custom hook until the template solution is implemented as template version will be more flexible

luc-github commented 2 years ago

@cyberiano here my proposal for the template, it is based on what is already implemented :

Possible variables:

$T1$ = token 1
$T2$ = token 2
$TS$ = token setting
$T1_64$ = token 1 (64-bit)
$T2_64$ = token 2 (64-bit)
$TS_64$ = token setting (64-bit)
$ESP_NAME$ = ESP hostname
$ESP_IP$ = ESP3D IP
$MSG$ = from ESP600 or AUTOMSG => message which also can contain $ESP_NAME$ and $ESP_IP$
$DATA$ = expansion of DATA entry
$DATALEN$ = length of DATA entry after expension 

Common entries that are mandatories or optional in parenthesis default value:

address = () error if empty => the server address, error if empty 
port = (443) => the server port
https = (yes) =>need secure server or not 
timeout = (5000) =>connection timeout
Trigger1 = () => starting trigger for success, error if empty
Trigger1 = (trigger1) =>trigger for success, same as trigger 1 if ommited
DATA =() => the payload
CMD  = the command line with verb, header , payload sizze and payload
AUTOMSG = () => the message for autonotification at boot, if empty no auto notification is done

Sample entries used as reference: 1 - PUSHOVER

DATA = user=$T1$&token=$T2$&title=ESP3D&message=$MSG&device=$ESPNAME$
CMD = POST /1/messages.json HTTP/1.1\r\nHost: api.pushover.net\r\nConnection: close\r\nCache-Control: no-cache\r\nUser-Agent: ESP3D\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nContent-Length: $DATALEN$\r\n\r\n$DATA$
Trigger1 = {
Trigger2 = "status":1

2 - TELEGRAM

DATA = chat_id=$T2$&text=$MSG$
CMD = POST /bot$t1$/sendMessage HTTP/1.1\r\nHost: api.telegram.org\r\nConnection: close\r\nContent-Type: application/x-www-form-urlencoded\r\nCache-Control: no-cache\r\nUser-Agent: ESP3D\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nContent-Length:$DATALEN$\r\n\r\n$DATA$"
Trigger1 = {
Trigger2 = "ok":true

3 - LINE

DATA = message=$MSG$
CMD = POST /api/notify HTTP/1.1\r\nHost: notify-api.line.me\r\nConnection: close\r\nCache-Control: no-cache\r\nUser-Agent: ESP3D\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nContent-Type: application/x-www-form-urlencoded\r\nAuthorization: Bearer $T1$\r\nContent-Length: $DATALEN$\r\n\r\n$DATA$
Trigger1 = {
Trigger2 = "status":200

4 - IFTTT

DATA = value1=ESP3D Notification&value2=$MSG$&value3=$ESPNAME$
CMD  = POST /trigger/$T1$/with/key/$T2$  HTTP/1.1\r\nHost: maker.ifttt.com\r\nConnection: close\r\nCache-Control: no-cache\r\nUser-Agent: ESP3D\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: $DATALEN$\r\n\r\n$DATA$
Trigger1 = Congratulations
Trigger2 = Congratulations

the template file could be in root of file system, e.g: notification.tpl

Example 1(based on IFTTT webhook): 1 - Complete version

address= myserver.local
port = 443
https = yes
timeout = 5000
Trigger1 =Congratulations
Trigger2 =Congratulations
DATA = value1=ESP3D Notification&value2=$MSG$&value3=$ESPNAME$
CMD  = POST /trigger/$T1$/with/key/$T2$  HTTP/1.1\r\nHost: Homeassistant\r\nConnection: close\r\nCache-Control: no-cache\r\nUser-Agent: ESP3D\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: $DATALEN$\r\n\r\n$DATA$
AUTOMSG = Hello, $ESP_NAME$ is now online at http://$ESP_IP$

2 - Minimal version (removing optional entries suing default values)

address = myserver.local
Trigger1 =Congratulations
DATA = value1=ESP3D Notification&value2=$MSG$&value3=$ESPNAME$
CMD  = POST /trigger/$T1$/with/key/$T2$  HTTP/1.1\r\nHost: maker.ifttt.com\r\nConnection: close\r\nCache-Control: no-cache\r\nUser-Agent: ESP3D\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: $DATALEN$\r\n\r\n$DATA$
AUTOMSG = Hello, $ESP_NAME$ is now online at http://$ESP_IP$

Example 2 (based on your example where t1 = hookId):

address = your-home-assistant
port = 8123
Trigger1 ="status": 200
DATA = { 'key': '$MSG$'}
CMD  = POST /api/webhook/$T1$  HTTP/1.1\r\nHost:.home-assistant.io\r\nConnection: close\r\nCache-Control: no-cache\r\nUser-Agent: ESP3D\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: $DATALEN$\r\n\r\n$DATA$
AUTOMSG = $ESP_IP

Like this is it is pretty flexible I think, it allows control every part of the querie, it can be elaborate to add more user case if FW allow it (e.g: error message)

What do you think ?

stale[bot] commented 2 years ago

This issue has been removed from the stale queue. Please ensure activity to keep it openin the future.