Hi, first i would like to say thank you for this amazing project.
Currently i am struggling with some points.
I cant see the sensors in HA.
Here is my config.yaml:
template:
# Snapmaker Guide
- trigger:
- platform: webhook
webhook_id: whsnapmakera250t
local_only: true
allowed_methods:
- POST
- PUT
sensor:
- name: "SnapMaker 2.0 A250T"
icon: mdi:printer-3d
unique_id: "sensor.glados_state"
state: "{{ (trigger.json | from_json)['status'] }}"
attributes:
ip: "{{ (trigger.json | from_json)['ip'] }}"
x: "{{ (trigger.json | from_json)['x'] }}"
y: "{{ (trigger.json | from_json)['y'] }}"
z: "{{ (trigger.json | from_json)['z'] }}"
homed: "{{ (trigger.json | from_json)['homed'] }}"
offsetX: "{{ (trigger.json | from_json)['offsetX'] }}"
offsetY: "{{ (trigger.json | from_json)['offsetY'] }}"
offsetZ: "{{ (trigger.json | from_json)['offsetZ'] }}"
toolHead: "{{ (trigger.json | from_json)['toolHead'] }}"
nozzleTemperature: "{{ (trigger.json | from_json)['nozzleTemperature'] }}"
nozzleTargetTemperature: "{{ (trigger.json | from_json)['nozzleTargetTemperature'] }}"
nozzleTemperature2: "{{ (trigger.json | from_json)['nozzleTemperature2'] }}"
nozzleTargetTemperature2: "{{ (trigger.json | from_json)['nozzleTargetTemperature2'] }}"
heatedBedTemperature: "{{ (trigger.json | from_json)['heatedBedTemperature'] }}"
heatedBedTargetTemperature: "{{ (trigger.json | from_json)['heatedBedTargetTemperature'] }}"
isFilamentOut: "{{ (trigger.json | from_json)['isFilamentOut'] }}"
spindleSpeed: "{{ (trigger.json | from_json)['spindleSpeed'] }}"
laserFocalLength: "{{ (trigger.json | from_json)['laserFocalLength'] }}"
laserPower: "{{ (trigger.json | from_json)['laserPower'] }}"
laserCamera: "{{ (trigger.json | from_json)['laserCamera'] }}"
laser10WErrorState: "{{ (trigger.json | from_json)['laser10WErrorState'] }}"
workSpeed: "{{ (trigger.json | from_json)['workSpeed'] }}"
printStatus: "{{ (trigger.json | from_json)['printStatus'] }}"
fileName: "{{ (trigger.json | from_json)['fileName'] }}"
totalLines: "{{ (trigger.json | from_json)['totalLines'] }}"
currentLine: "{{ (trigger.json | from_json)['currentLine'] }}"
progress: "{{ (trigger.json | from_json)['progress'] }}"
estimatedTime: "{{ (trigger.json | from_json)['estimatedTime'] }}"
elapsedTime: "{{ (trigger.json | from_json)['elapsedTime'] }}"
remainingTime: "{{ (trigger.json | from_json)['remainingTime'] }}"
enclosure: "{{ (trigger.json | from_json)['moduleList']['enclosure'] }}"
rotaryModule: "{{ (trigger.json | from_json)['moduleList']['rotaryModule'] }}"
emergencyStopButton: "{{ (trigger.json | from_json)['moduleList']['emergencyStopButton'] }}"
airPurifier: "{{ (trigger.json | from_json)['moduleList']['airPurifier'] }}"
isEnclosureDoorOpen: "{{ (trigger.json | from_json)['isEnclosureDoorOpen'] }}"
doorSwitchCount: "{{ (trigger.json | from_json)['doorSwitchCount'] }}"
The script is running from a different container and is sending data via webhook to ha.
this is the script:
#!/usr/bin/python3
# Requires: sudo pip3 install requests
#
import socket
import requests
import json
import urllib3
import ipaddress
import time
from datetime import timedelta
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
haToken = "yourAPItoken" # Set your HomeAssistant API Token
whUrl = 'http://10.0.0.99:8123/api/webhook/whsnapmakera250t' # Set to your HomeAssistant WebHook URL
bufferSize = 1024
msg = b'discover'
destPort = 20054
sockTimeout = 1.0
retries = 5
retryCounter = 0
snReply = {}
connectIP = ''
tokenfile = '/root/SMtoken.txt' # Set to writable path, file will be created if not exists.
snWorking = ''
# Main Program
def main():
global connectIP
UDPClientSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
UDPClientSocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
UDPClientSocket.settimeout(sockTimeout)
# Get Status and IP of Snapmaker
checkState(UDPClientSocket,msg,destPort,retries)
if validate_ip_address(snReply.get("snIP")):
connectIP = snReply.get("snIP")
print("Snapmaker found:", connectIP)
if snWorking == 'IDLE':
SMtoken = getSMToken(connectIP)
postIt(snReply)
else:
SMtoken = getSMToken(connectIP)
print("Connecting with Token:",SMtoken)
postIt(readStatus(SMtoken))
# Not yet used
#readStatusEnclosure(SMtoken)
else:
postIt(snReply)
print("No Snapmaker found.")
def getSMToken(connectIP):
# Create file if not exists
try:
f = open(tokenfile, "r+")
except FileNotFoundError:
f = open(tokenfile, "w+")
SMurl = "http://" + connectIP + ":8080/api/v1/connect"
SMtoken = f.read()
if SMtoken == "":
# Create token
connected = False
while not connected:
r = requests.post(SMurl)
print("Please authorize on Touchscreen.")
time.sleep(60)
if "Failed" in r.text:
print(r.text)
print("Binding failed, please restart script")
exit(1)
SMtoken = (json.loads(r.text).get("token"))
headers = {'Content-Type' : 'application/x-www-form-urlencoded'}
formData = {'token' : SMtoken}
r = requests.post(SMurl, data=formData, headers=headers)
if json.loads(r.text).get("token") == SMtoken:
f.write(SMtoken)
print("Token received and saved.\nRestart Script for autoconnect now.")
connected = True
return(SMtoken)
exit(0)
else:
f.close()
# Connect to SnapMaker with saved token
headers = {'Content-Type' : 'application/x-www-form-urlencoded'}
formData = {'token' : SMtoken}
r = requests.post(SMurl, data=formData, headers=headers)
return(SMtoken)
# Read Status of Snapmaker 2.0 via API
# Example Data IDLE:
# {"status":"IDLE","x":112,"y":142,"z":150,"homed":false,"offsetX":0,"offsetY":0,"offsetZ":0,"toolHead":"TOOLHEAD_3DPRINTING_1",
# "nozzleTemperature":19,"nozzleTargetTemperature":0,"heatedBedTemperature":20,"heatedBedTargetTemperature":0,
# "isFilamentOut":false,"workSpeed":1500,"printStatus":"Idle",
# "moduleList":{"enclosure":true,"rotaryModule":false,"emergencyStopButton":true,"airPurifier":false},
# "isEnclosureDoorOpen":false,"doorSwitchCount":0}
#
# Example Data RUNNING:
# {"status":"RUNNING","x":-19,"y":339,"z":310.763,"homed":false,"offsetX":0,"offsetY":0,"offsetZ":0,"toolHead":"TOOLHEAD_3DPRINTING_1",
# "nozzleTemperature":63,"nozzleTargetTemperature":205,"heatedBedTemperature":20,"heatedBedTargetTemperature":70,
# "isFilamentOut":false,"workSpeed":1500,"printStatus":"Printing",
# "fileName":"Leon_Base.gcode","totalLines":20295,"estimatedTime":3204,"currentLine":91,"progress":0.004483863245695829,"elapsedTime":20,"remainingTime":3195,
# "moduleList":{"enclosure":true,"rotaryModule":false,"emergencyStopButton":true,"airPurifier":false},
# "isEnclosureDoorOpen":false,"doorSwitchCount":0}
#
def readStatus(SMtoken):
#print("Reading SN Status...")
SMstatus = "http://" + connectIP + ":8080/api/v1/status?token="
r = requests.get(SMstatus+SMtoken)
snStatus = json.loads(r.text).get("status")
snNozzleTemp = json.loads(r.text).get("nozzleTemperature")
snNozzleTaTemp = json.loads(r.text).get("nozzleTargetTemperature")
snHeatedBedTemp = json.loads(r.text).get("heatedBedTemperature")
snHeatedBedTaTemp = json.loads(r.text).get("heatedBedTargetTemperature")
if json.loads(r.text).get("fileName") is not None:
snFileName = json.loads(r.text).get("fileName")
else:
snFileName = "N/A"
if json.loads(r.text).get("progress") is not None:
snProgress = ("{:0.1f}".format(json.loads(r.text).get("progress")*100))
else:
snProgress = "0"
if json.loads(r.text).get("elapsedTime") is not None:
snElapsedTime = str(timedelta(seconds=json.loads(r.text).get("elapsedTime")))
else:
snElapsedTime = "00:00:00"
if json.loads(r.text).get("remainingTime") is not None:
snRemainingTime = str(timedelta(seconds=json.loads(r.text).get("remainingTime")))
else:
snRemainingTime = "00:00:00"
snReply = {"snIP":connectIP,"snStatus":snStatus,"snNozzleTemp":snNozzleTemp,"snNozzleTaTemp":snNozzleTaTemp,
"snHeatedBedTemp":snHeatedBedTemp,"snHeatedBedTaTemp":snHeatedBedTaTemp,"snFileName":snFileName,
"snProgress":snProgress,"snElapsedTime":snElapsedTime,"snRemainingTime":snRemainingTime}
return(snReply)
# Read Status of Enclosure
# Example Data:
# {"isReady":true,"isDoorEnabled":false,"led":100,"fan":0}
#
def readStatusEnclosure(SMtoken):
print("Reading Enclosure Status...")
SMenclosure = "http://" + connectIP + ":8080/api/v1/enclosure?token="
r = requests.get(SMenclosure+SMtoken)
print(r.text)
return(r.text)
# Check status of Snapmaker 2.0 via UDP Discovery
# Possible replies:
# '[email protected]|model:Snapmaker 2 Model A350|status:IDLE'
# '[email protected]|model:Snapmaker 2 Model A350|status:RUNNING'
def checkState(UDPClientSocket,msg,destPort,retries):
global snReply
global snWorking
global retryCounter
UDPClientSocket.sendto(msg, ("255.255.255.255", destPort))
try:
reply, server_address_info = UDPClientSocket.recvfrom(1024)
elements = str(reply).split('|')
snIP = (elements[0]).replace('\'','')
snModel = (elements[1]).replace('\'','')
snStatus = (elements[2]).replace('\'','')
snIP, snIPVal = snIP.split('@')
snModel, snModelVal = snModel.split(':')
snStatus, snStatusVal = snStatus.split(':')
snWorking = snStatusVal
snReply = {"snIP":snIPVal, "model":snModelVal, "snStatus":snStatusVal}
except socket.timeout:
retryCounter += 1
if (retryCounter==retries):
snReply = {"snIP":"N/A", "model":"N/A", "snStatus":"OFFLINE",
"snNozzleTemp":0,"snNozzleTaTemp":0,
"snHeatedBedTemp":0,"snHeatedBedTaTemp":0,"snFileName":"N/A",
"snProgress":0,"snElapsedTime":"00:00:00","snRemainingTime":"00:00:00"}
return
else:
checkState(UDPClientSocket,msg,destPort,retries);
# Check if IP is valid:
def validate_ip_address(ip_string):
try:
ip_object = ipaddress.ip_address(ip_string)
return True
except ValueError:
return False
# POST to HomeAssistant Webhook
def postIt(state):
session = requests.Session()
session.verify = False
print("Sending State:", state)
try:
requests.post(whUrl, json = state, verify=False)
except requests.exceptions.ConnectionError:
print("Could not connect to HomeAssistant on", whUrl)
return
# Run Main Program
main()
If i got this running my next steps would be trying to run this directly from HA. I tried this, but my HA got freezed every time i tried to run it via python_script.
Many thanks in advance
Best regards