mirror of
https://github.com/joBr99/nspanel-lovelace-ui.git
synced 2025-12-19 22:24:15 +01:00
swap default tasmota driver
This commit is contained in:
@@ -192,8 +192,6 @@ See Tasmota [MQTT Documentation](https://tasmota.github.io/docs/MQTT/) for more
|
|||||||
|
|
||||||
Upload the nspanel.tft from the lastest release to a Webserver (for example www folder of Home Assistant) and execute the following command in Tasmota Console. (Development Version: [tft file from HMI folder](HMI/nspanel.tft))
|
Upload the nspanel.tft from the lastest release to a Webserver (for example www folder of Home Assistant) and execute the following command in Tasmota Console. (Development Version: [tft file from HMI folder](HMI/nspanel.tft))
|
||||||
|
|
||||||
**Webserver needs to support HTTP Range Header Requests, python2/3 http server doesn't work**
|
|
||||||
|
|
||||||
**Webserver must be HTTP, HTTPS is not supported, due to limitations of berry lang on tasmota**
|
**Webserver must be HTTP, HTTPS is not supported, due to limitations of berry lang on tasmota**
|
||||||
|
|
||||||
`FlashNextion http://ip-address-of-your-homeassistant:8123/local/nspanel.tft`
|
`FlashNextion http://ip-address-of-your-homeassistant:8123/local/nspanel.tft`
|
||||||
@@ -346,8 +344,7 @@ Since release 1.1 you can update the berry driver directly from the Tasmota Cons
|
|||||||
### Flashing of the Display Firmware with FlashNextion doesn't work
|
### Flashing of the Display Firmware with FlashNextion doesn't work
|
||||||
|
|
||||||
1. Make sure to use the [tasmota32-nspanel.bin](https://github.com/tasmota/install/raw/main/firmware/unofficial/tasmota32-nspanel.bin) Tasmota build.
|
1. Make sure to use the [tasmota32-nspanel.bin](https://github.com/tasmota/install/raw/main/firmware/unofficial/tasmota32-nspanel.bin) Tasmota build.
|
||||||
2. Make sure to use an WebServer which supports http range requests like HomeAssistant, apache2 or nginx for exmaple.
|
2. Make sure to use HTTP and **not HTTPS**
|
||||||
3. Make sure to use HTTP and **not HTTPS**
|
|
||||||
|
|
||||||
### My flashing doesn't start at all
|
### My flashing doesn't start at all
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ babel_spec = importlib.util.find_spec("babel")
|
|||||||
if babel_spec is not None:
|
if babel_spec is not None:
|
||||||
import babel.dates
|
import babel.dates
|
||||||
|
|
||||||
|
|
||||||
class NsPanelLovelaceUIManager(hass.Hass):
|
class NsPanelLovelaceUIManager(hass.Hass):
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
|
|
||||||
@@ -77,7 +76,7 @@ class NsPanelLovelaceUI:
|
|||||||
# Parse Json Message from Tasmota and strip out message from nextion display
|
# Parse Json Message from Tasmota and strip out message from nextion display
|
||||||
data = json.loads(data["payload"])
|
data = json.loads(data["payload"])
|
||||||
if("CustomRecv" not in data):
|
if("CustomRecv" not in data):
|
||||||
self.api.log("Received Message from Tasmota: %s", data, level="DEBUG")
|
self.api.log("Received Message from Tasmota, but not from nextion screen: %s", data, level="DEBUG")
|
||||||
return
|
return
|
||||||
msg = data["CustomRecv"]
|
msg = data["CustomRecv"]
|
||||||
self.api.log("Received Message from Tasmota: %s", msg) #, level="DEBUG"
|
self.api.log("Received Message from Tasmota: %s", msg) #, level="DEBUG"
|
||||||
@@ -86,17 +85,11 @@ class NsPanelLovelaceUI:
|
|||||||
msg = msg.split(",")
|
msg = msg.split(",")
|
||||||
|
|
||||||
# run action based on received command
|
# run action based on received command
|
||||||
# TODO: replace with match case after appdeamon container swiched to python 3.10 - https://pakstech.com/blog/python-switch-case/ - https://www.python.org/dev/peps/pep-0636/
|
|
||||||
if msg[0] == "event":
|
if msg[0] == "event":
|
||||||
|
|
||||||
if msg[1] == "startup":
|
if msg[1] == "startup":
|
||||||
self.api.log("Handling startup event", level="DEBUG")
|
self.api.log("Handling startup event", level="DEBUG")
|
||||||
|
|
||||||
# grab version from screen
|
|
||||||
current_panel_version = int(msg[2])
|
|
||||||
self.api.log("Nextion Display reports version: %s; Checking for updates ...", current_panel_version)
|
|
||||||
|
|
||||||
|
|
||||||
# send date and time
|
# send date and time
|
||||||
self.update_time("")
|
self.update_time("")
|
||||||
self.update_date("")
|
self.update_date("")
|
||||||
@@ -205,60 +198,64 @@ class NsPanelLovelaceUI:
|
|||||||
|
|
||||||
|
|
||||||
def handle_button_press(self, entity_id, btype, optVal=None):
|
def handle_button_press(self, entity_id, btype, optVal=None):
|
||||||
if(btype == "OnOff"):
|
if entity_id == "updateNoYes" and optVal == "yes":
|
||||||
if(optVal == "1"):
|
self.api.log("Sending update command")
|
||||||
|
self.mqtt.mqtt_publish(self.config["panelSendTopic"].replace("CustomSend", "FlashNextion"), release_config_desired_display_firmware_url)
|
||||||
|
|
||||||
|
if btype == "OnOff":
|
||||||
|
if optVal == "1":
|
||||||
self.api.turn_on(entity_id)
|
self.api.turn_on(entity_id)
|
||||||
else:
|
else:
|
||||||
self.api.turn_off(entity_id)
|
self.api.turn_off(entity_id)
|
||||||
if(btype == "up"):
|
if btype == "up":
|
||||||
self.api.get_entity(entity_id).call_service("open_cover")
|
self.api.get_entity(entity_id).call_service("open_cover")
|
||||||
if(btype == "stop"):
|
if btype == "stop":
|
||||||
self.api.get_entity(entity_id).call_service("stop_cover")
|
self.api.get_entity(entity_id).call_service("stop_cover")
|
||||||
if(btype == "down"):
|
if btype == "down":
|
||||||
self.api.get_entity(entity_id).call_service("close_cover")
|
self.api.get_entity(entity_id).call_service("close_cover")
|
||||||
|
|
||||||
if(btype == "button"):
|
if btype == "button":
|
||||||
if(entity_id.startswith('scene')):
|
if entity_id.startswith('scene'):
|
||||||
self.api.get_entity(entity_id).call_service("turn_on")
|
self.api.get_entity(entity_id).call_service("turn_on")
|
||||||
if(entity_id.startswith('light') or entity_id.startswith('switch')):
|
if entity_id.startswith('light') or entity_id.startswith('switch'):
|
||||||
self.api.get_entity(entity_id).call_service("toggle")
|
self.api.get_entity(entity_id).call_service("toggle")
|
||||||
else:
|
else:
|
||||||
self.api.get_entity(entity_id).call_service("press")
|
self.api.get_entity(entity_id).call_service("press")
|
||||||
|
|
||||||
if(btype == "media-next"):
|
if btype == "media-next":
|
||||||
self.api.get_entity(entity_id).call_service("media_next_track")
|
self.api.get_entity(entity_id).call_service("media_next_track")
|
||||||
if(btype == "media-back"):
|
if btype == "media-back":
|
||||||
self.api.get_entity(entity_id).call_service("media_previous_track")
|
self.api.get_entity(entity_id).call_service("media_previous_track")
|
||||||
if(btype == "media-pause"):
|
if btype == "media-pause":
|
||||||
self.api.get_entity(entity_id).call_service("media_play_pause")
|
self.api.get_entity(entity_id).call_service("media_play_pause")
|
||||||
|
|
||||||
if(btype == "hvac_action"):
|
if btype == "hvac_action":
|
||||||
self.api.get_entity(entity_id).call_service("set_hvac_mode", hvac_mode=optVal)
|
self.api.get_entity(entity_id).call_service("set_hvac_mode", hvac_mode=optVal)
|
||||||
|
|
||||||
|
|
||||||
if(btype == "brightnessSlider"):
|
if btype == "brightnessSlider":
|
||||||
# scale 0-100 to ha brightness range
|
# scale 0-100 to ha brightness range
|
||||||
brightness = int(scale(int(optVal),(0,100),(0,255)))
|
brightness = int(scale(int(optVal),(0,100),(0,255)))
|
||||||
self.api.get_entity(entity_id).call_service("turn_on", brightness=brightness)
|
self.api.get_entity(entity_id).call_service("turn_on", brightness=brightness)
|
||||||
|
|
||||||
if(btype == "colorTempSlider"):
|
if btype == "colorTempSlider":
|
||||||
entity = self.api.get_entity(entity_id)
|
entity = self.api.get_entity(entity_id)
|
||||||
#scale 0-100 from slider to color range of lamp
|
#scale 0-100 from slider to color range of lamp
|
||||||
color_val = scale(int(optVal), (0, 100), (entity.attributes.min_mireds, entity.attributes.max_mireds))
|
color_val = scale(int(optVal), (0, 100), (entity.attributes.min_mireds, entity.attributes.max_mireds))
|
||||||
self.api.get_entity(entity_id).call_service("turn_on", color_temp=color_val)
|
self.api.get_entity(entity_id).call_service("turn_on", color_temp=color_val)
|
||||||
|
|
||||||
if(btype == "colorWheel"):
|
if btype == "colorWheel":
|
||||||
self.api.log(optVal)
|
self.api.log(optVal)
|
||||||
optVal = optVal.split('|')
|
optVal = optVal.split('|')
|
||||||
color = pos_to_color(int(optVal[0]), int(optVal[1]))
|
color = pos_to_color(int(optVal[0]), int(optVal[1]))
|
||||||
self.api.log(color)
|
self.api.log(color)
|
||||||
self.api.get_entity(entity_id).call_service("turn_on", rgb_color=color)
|
self.api.get_entity(entity_id).call_service("turn_on", rgb_color=color)
|
||||||
|
|
||||||
if(btype == "positionSlider"):
|
if btype == "positionSlider":
|
||||||
pos = int(optVal)
|
pos = int(optVal)
|
||||||
self.api.get_entity(entity_id).call_service("set_cover_position", position=pos)
|
self.api.get_entity(entity_id).call_service("set_cover_position", position=pos)
|
||||||
|
|
||||||
if(btype == "volumeSlider"):
|
if btype == "volumeSlider":
|
||||||
pos = int(optVal)
|
pos = int(optVal)
|
||||||
# HA wants this value between 0 and 1 as float
|
# HA wants this value between 0 and 1 as float
|
||||||
pos = pos/100
|
pos = pos/100
|
||||||
@@ -575,5 +572,5 @@ class NsPanelLovelaceUI:
|
|||||||
|
|
||||||
def send_message_page(self, id, heading, msg, b1, b2):
|
def send_message_page(self, id, heading, msg, b1, b2):
|
||||||
self.send_mqtt_msg(f"pageType,popupNotify")
|
self.send_mqtt_msg(f"pageType,popupNotify")
|
||||||
self.send_mqtt_msg(f"entityUpdateDetail,{id},{heading},65535,{b2},65535,{b2},65535,{msg},65535")
|
self.send_mqtt_msg(f"entityUpdateDetail,|{id}|{heading}|65535|{b1}|65535|{b2}|65535|{msg}|65535|0")
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,44 @@
|
|||||||
# Nextion Berry Driver
|
# Nextion Berry Driver
|
||||||
|
|
||||||
|
This berry driver is intended for the usage with a custom HMI/TFT firmware on nspanel and is a customisted version form [peepshow-21's ns-flash](https://github.com/peepshow-21/ns-flash)
|
||||||
|
|
||||||
|
It adds the following commands to Tasmota:
|
||||||
|
|
||||||
|
- `Nextion Payload`
|
||||||
|
|
||||||
|
Send's normal Nextion Commands to the Screen (suffixed by 0xFFFFFF)
|
||||||
|
|
||||||
|
|
||||||
|
- `CustomSend Payload`
|
||||||
|
|
||||||
|
Send's normal Custom Commands to the Screen in the following format:
|
||||||
|
`55 BB [payload length] [payload] [crc] [crc]`
|
||||||
|
|
||||||
|
- `FlashNextion URL`
|
||||||
|
|
||||||
|
Start's flashing a tft file to the nextion screen via Nextion Upload Protocol 1.2
|
||||||
|
|
||||||
|
Webserver must be reachable via HTTP
|
||||||
|
|
||||||
|
Example: `FlashNextion http://192.168.75.30:8123/local/nspanel.tft`
|
||||||
|
|
||||||
|
- `GetDriverVersion`
|
||||||
|
|
||||||
|
Returns the version currently defined in the berry script
|
||||||
|
|
||||||
|
- `UpdateDriverVersion URL`
|
||||||
|
|
||||||
|
Downloads the autoexec.be script from the specified URL and loads it.
|
||||||
|
|
||||||
|
|
||||||
|
Besides the commands, serial input will be published on 'RESULT' Topic, depending on the input in one of the following formats:
|
||||||
|
- `{"CustomRecv":%s}`
|
||||||
|
- `{"nextion":%s}`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Nextion Berry Driver Legacy Range (Old version with HTTP Range Method)
|
||||||
|
|
||||||
This berry driver is intended for the usage with a custom HMI/TFT firmware on nspanel.
|
This berry driver is intended for the usage with a custom HMI/TFT firmware on nspanel.
|
||||||
|
|
||||||
It adds the following commands to Tasmota:
|
It adds the following commands to Tasmota:
|
||||||
|
|||||||
@@ -1,388 +0,0 @@
|
|||||||
# Sonoff NSPanel Tasmota Lovelace UI Berry Driver | code by joBr99
|
|
||||||
# based on;
|
|
||||||
# Sonoff NSPanel Tasmota (Nextion with Flashing) driver | code by peepshow-21
|
|
||||||
# based on;
|
|
||||||
# Sonoff NSPanel Tasmota driver v0.47 | code by blakadder and s-hadinger
|
|
||||||
|
|
||||||
# Example Flash
|
|
||||||
# FlashNextion http://ip-address-of-your-homeassistant:8123/local/nspanel.tft
|
|
||||||
# FlashNextion http://nspanel.pky.eu/lui.tft
|
|
||||||
|
|
||||||
class Nextion : Driver
|
|
||||||
|
|
||||||
static VERSION = "1.1.3"
|
|
||||||
static header = bytes('55BB')
|
|
||||||
|
|
||||||
static flash_block_size = 4096
|
|
||||||
|
|
||||||
var flash_mode
|
|
||||||
var flash_size
|
|
||||||
var flash_written
|
|
||||||
var flash_buff
|
|
||||||
var flash_offset
|
|
||||||
var awaiting_offset
|
|
||||||
var tcp
|
|
||||||
var ser
|
|
||||||
var last_per
|
|
||||||
|
|
||||||
def split_55(b)
|
|
||||||
var ret = []
|
|
||||||
var s = size(b)
|
|
||||||
var i = s-2 # start from last-1
|
|
||||||
while i > 0
|
|
||||||
if b[i] == 0x55 && b[i+1] == 0xBB
|
|
||||||
ret.push(b[i..s-1]) # push last msg to list
|
|
||||||
b = b[(0..i-1)] # write the rest back to b
|
|
||||||
end
|
|
||||||
i -= 1
|
|
||||||
end
|
|
||||||
ret.push(b)
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
def crc16(data, poly)
|
|
||||||
if !poly poly = 0xA001 end
|
|
||||||
# CRC-16 MODBUS HASHING ALGORITHM
|
|
||||||
var crc = 0xFFFF
|
|
||||||
for i:0..size(data)-1
|
|
||||||
crc = crc ^ data[i]
|
|
||||||
for j:0..7
|
|
||||||
if crc & 1
|
|
||||||
crc = (crc >> 1) ^ poly
|
|
||||||
else
|
|
||||||
crc = crc >> 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return crc
|
|
||||||
end
|
|
||||||
|
|
||||||
# encode using custom protocol 55 BB [payload length] [payload length] [payload] [crc] [crc]
|
|
||||||
def encode(payload)
|
|
||||||
var b = bytes()
|
|
||||||
b += self.header
|
|
||||||
b.add(size(payload), 2) # add size as 2 bytes, little endian
|
|
||||||
b += bytes().fromstring(payload)
|
|
||||||
var msg_crc = self.crc16(b)
|
|
||||||
b.add(msg_crc, 2) # crc 2 bytes, little endian
|
|
||||||
return b
|
|
||||||
end
|
|
||||||
|
|
||||||
def encodenx(payload)
|
|
||||||
var b = bytes().fromstring(payload)
|
|
||||||
b += bytes('FFFFFF')
|
|
||||||
return b
|
|
||||||
end
|
|
||||||
|
|
||||||
def sendnx(payload)
|
|
||||||
import string
|
|
||||||
var payload_bin = self.encodenx(payload)
|
|
||||||
self.ser.write(payload_bin)
|
|
||||||
log(string.format("NXP: Nextion command sent = %s",str(payload_bin)), 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
def send(payload)
|
|
||||||
var payload_bin = self.encode(payload)
|
|
||||||
if self.flash_mode==1
|
|
||||||
log("NXP: skipped command becuase still flashing", 3)
|
|
||||||
else
|
|
||||||
self.ser.write(payload_bin)
|
|
||||||
log("NXP: payload sent = " + str(payload_bin), 3)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def write_to_nextion(b)
|
|
||||||
self.ser.write(b)
|
|
||||||
end
|
|
||||||
|
|
||||||
def screeninit()
|
|
||||||
log("NXP: Screen Initialized")
|
|
||||||
self.sendnx("recmod=1")
|
|
||||||
end
|
|
||||||
|
|
||||||
def write_block()
|
|
||||||
|
|
||||||
import string
|
|
||||||
log("FLH: Read block",3)
|
|
||||||
while size(self.flash_buff)<self.flash_block_size && self.tcp.connected()
|
|
||||||
if self.tcp.available()>0
|
|
||||||
self.flash_buff += self.tcp.readbytes()
|
|
||||||
else
|
|
||||||
tasmota.delay(50)
|
|
||||||
log("FLH: Wait for available...",3)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
log("FLH: Buff size "+str(size(self.flash_buff)),3)
|
|
||||||
var to_write
|
|
||||||
if size(self.flash_buff)>self.flash_block_size
|
|
||||||
to_write = self.flash_buff[0..self.flash_block_size-1]
|
|
||||||
self.flash_buff = self.flash_buff[self.flash_block_size..]
|
|
||||||
else
|
|
||||||
to_write = self.flash_buff
|
|
||||||
self.flash_buff = bytes()
|
|
||||||
end
|
|
||||||
log("FLH: Writing "+str(size(to_write)),3)
|
|
||||||
var per = (self.flash_written*100)/self.flash_size
|
|
||||||
if (self.last_per!=per)
|
|
||||||
self.last_per = per
|
|
||||||
tasmota.publish_result(string.format("{\"Flashing\":{\"complete\": %d}}",per), "RESULT")
|
|
||||||
end
|
|
||||||
if size(to_write)>0
|
|
||||||
self.flash_written += size(to_write)
|
|
||||||
if self.flash_offset==0 || self.flash_written>self.flash_offset
|
|
||||||
self.ser.write(to_write)
|
|
||||||
self.flash_offset = 0
|
|
||||||
else
|
|
||||||
tasmota.set_timer(10,/->self.write_block())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
log("FLH: Total "+str(self.flash_written),3)
|
|
||||||
if (self.flash_written==self.flash_size)
|
|
||||||
log("FLH: Flashing complete")
|
|
||||||
self.flash_mode = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
def every_100ms()
|
|
||||||
import string
|
|
||||||
if self.ser.available() > 0
|
|
||||||
var msg = self.ser.read()
|
|
||||||
if size(msg) > 0
|
|
||||||
log(string.format("NXP: Received Raw = %s",str(msg)), 3)
|
|
||||||
if (self.flash_mode==1)
|
|
||||||
var strv = msg[0..-4].asstring()
|
|
||||||
if string.find(strv,"comok 2")>=0
|
|
||||||
log("FLH: Send (High Speed) flash start")
|
|
||||||
self.sendnx(string.format("whmi-wris %d,115200,res0",self.flash_size))
|
|
||||||
elif size(msg)==1 && msg[0]==0x08
|
|
||||||
log("FLH: Waiting offset...",3)
|
|
||||||
self.awaiting_offset = 1
|
|
||||||
elif size(msg)==4 && self.awaiting_offset==1
|
|
||||||
self.awaiting_offset = 0
|
|
||||||
self.flash_offset = msg.get(0,4)
|
|
||||||
log("FLH: Flash offset marker "+str(self.flash_offset),3)
|
|
||||||
self.write_block()
|
|
||||||
elif size(msg)==1 && msg[0]==0x05
|
|
||||||
self.write_block()
|
|
||||||
else
|
|
||||||
log("FLH: Something has gone wrong flashing display firmware ["+str(msg)+"]",2)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
var msg_list = self.split_55(msg)
|
|
||||||
for i:0..size(msg_list)-1
|
|
||||||
msg = msg_list[i]
|
|
||||||
if size(msg) > 0
|
|
||||||
if msg == bytes('000000FFFFFF88FFFFFF')
|
|
||||||
self.screeninit()
|
|
||||||
elif size(msg)>=2 && msg[0]==0x55 && msg[1]==0xBB
|
|
||||||
var jm = string.format("{\"CustomRecv\":\"%s\"}",msg[4..-3].asstring())
|
|
||||||
tasmota.publish_result(jm, "RESULT")
|
|
||||||
elif msg[0]==0x07 && size(msg)==1 # BELL/Buzzer
|
|
||||||
tasmota.cmd("buzzer 1,1")
|
|
||||||
else
|
|
||||||
var jm = string.format("{\"nextion\":\"%s\"}",str(msg[0..-4]))
|
|
||||||
tasmota.publish_result(jm, "RESULT")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def begin_nextion_flash()
|
|
||||||
self.flash_written = 0
|
|
||||||
self.awaiting_offset = 0
|
|
||||||
self.flash_offset = 0
|
|
||||||
self.sendnx('DRAKJHSUYDGBNCJHGJKSHBDN')
|
|
||||||
self.sendnx('recmod=0')
|
|
||||||
self.sendnx('recmod=0')
|
|
||||||
self.flash_mode = 1
|
|
||||||
self.sendnx("connect")
|
|
||||||
end
|
|
||||||
|
|
||||||
def open_url(url)
|
|
||||||
|
|
||||||
import string
|
|
||||||
var host
|
|
||||||
var port
|
|
||||||
var s1 = string.split(url,7)[1]
|
|
||||||
var i = string.find(s1,":")
|
|
||||||
var sa
|
|
||||||
if i<0
|
|
||||||
port = 80
|
|
||||||
i = string.find(s1,"/")
|
|
||||||
sa = string.split(s1,i)
|
|
||||||
host = sa[0]
|
|
||||||
else
|
|
||||||
sa = string.split(s1,i)
|
|
||||||
host = sa[0]
|
|
||||||
s1 = string.split(sa[1],1)[1]
|
|
||||||
i = string.find(s1,"/")
|
|
||||||
sa = string.split(s1,i)
|
|
||||||
port = int(sa[0])
|
|
||||||
end
|
|
||||||
var get = sa[1]
|
|
||||||
log(string.format("FLH: host: %s, port: %s, get: %s",host,port,get))
|
|
||||||
self.tcp = tcpclient()
|
|
||||||
self.tcp.connect(host,port)
|
|
||||||
log("FLH: Connected:"+str(self.tcp.connected()),3)
|
|
||||||
var get_req = "GET "+get+" HTTP/1.0\r\n"
|
|
||||||
get_req += string.format("HOST: %s:%s\r\n\r\n",host,port)
|
|
||||||
self.tcp.write(get_req)
|
|
||||||
var a = self.tcp.available()
|
|
||||||
i = 1
|
|
||||||
while a==0 && i<5
|
|
||||||
tasmota.delay(100*i)
|
|
||||||
tasmota.yield()
|
|
||||||
i += 1
|
|
||||||
log("FLH: Retry "+str(i),3)
|
|
||||||
a = self.tcp.available()
|
|
||||||
end
|
|
||||||
if a==0
|
|
||||||
log("FLH: Nothing available to read!",3)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
var b = self.tcp.readbytes()
|
|
||||||
i = 0
|
|
||||||
var end_headers = false;
|
|
||||||
var headers
|
|
||||||
while i<size(b) && headers==nil
|
|
||||||
if b[i..(i+3)]==bytes().fromstring("\r\n\r\n")
|
|
||||||
headers = b[0..(i+3)].asstring()
|
|
||||||
self.flash_buff = b[(i+4)..]
|
|
||||||
else
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
#print(headers)
|
|
||||||
# check http respose for code 200
|
|
||||||
var tag = "200 OK"
|
|
||||||
i = string.find(headers,tag)
|
|
||||||
if (i>0)
|
|
||||||
log("FLH: HTTP Respose is 200 OK",3)
|
|
||||||
else
|
|
||||||
log("FLH: HTTP Respose is not 200 OK",3)
|
|
||||||
print(headers)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
# check http respose for content-length
|
|
||||||
tag = "Content-Length: "
|
|
||||||
i = string.find(headers,tag)
|
|
||||||
if (i>0)
|
|
||||||
var i2 = string.find(headers,"\r\n",i)
|
|
||||||
var s = headers[i+size(tag)..i2-1]
|
|
||||||
self.flash_size=int(s)
|
|
||||||
end
|
|
||||||
if self.flash_size==0
|
|
||||||
log("FLH: No size header, counting ...",3)
|
|
||||||
self.flash_size = size(self.flash_buff)
|
|
||||||
#print("counting start ...")
|
|
||||||
while self.tcp.connected()
|
|
||||||
while self.tcp.available()>0
|
|
||||||
self.flash_size += size(self.tcp.readbytes())
|
|
||||||
end
|
|
||||||
tasmota.delay(50)
|
|
||||||
end
|
|
||||||
#print("counting end ...",self.flash_size)
|
|
||||||
self.tcp.close()
|
|
||||||
self.open_url(url)
|
|
||||||
else
|
|
||||||
log("FLH: Size found in header, skip count",3)
|
|
||||||
end
|
|
||||||
log("FLH: Flash file size: "+str(self.flash_size),3)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
def flash_nextion(url)
|
|
||||||
|
|
||||||
self.flash_size = 0
|
|
||||||
self.open_url(url)
|
|
||||||
self.begin_nextion_flash()
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
def version_number(str)
|
|
||||||
import string
|
|
||||||
var i1 = string.find(str,".",0)
|
|
||||||
var i2 = string.find(str,".",i1+1)
|
|
||||||
var num = int(str[0..i1-1])*10000+int(str[i1+1..i2-1])*100+int(str[i2+1..])
|
|
||||||
return num
|
|
||||||
end
|
|
||||||
|
|
||||||
def init()
|
|
||||||
log("NXP: Initializing Driver")
|
|
||||||
self.ser = serial(17, 16, 115200, serial.SERIAL_8N1)
|
|
||||||
self.flash_mode = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
var nextion = Nextion()
|
|
||||||
|
|
||||||
tasmota.add_driver(nextion)
|
|
||||||
|
|
||||||
def get_current_version(cmd, idx, payload, payload_json)
|
|
||||||
import string
|
|
||||||
var version_of_this_script = 2
|
|
||||||
var jm = string.format("{\"nlui_driver_version\":\"%s\"}", version_of_this_script)
|
|
||||||
tasmota.publish_result(jm, "RESULT")
|
|
||||||
end
|
|
||||||
|
|
||||||
tasmota.add_cmd('GetDriverVersion', get_current_version)
|
|
||||||
|
|
||||||
def update_berry_driver(cmd, idx, payload, payload_json)
|
|
||||||
def task()
|
|
||||||
import string
|
|
||||||
var cl = webclient()
|
|
||||||
cl.begin(payload)
|
|
||||||
var r = cl.GET()
|
|
||||||
if r == 200
|
|
||||||
print("Sucessfully downloaded nspanel-lovelace-ui berry driver")
|
|
||||||
else
|
|
||||||
print("Error while downloading nspanel-lovelace-ui berry driver")
|
|
||||||
end
|
|
||||||
r = cl.write_file("autoexec.be")
|
|
||||||
if r < 0
|
|
||||||
print("Error while writeing nspanel-lovelace-ui berry driver")
|
|
||||||
else
|
|
||||||
print("Scucessfully written nspanel-lovelace-ui berry driver")
|
|
||||||
var s = load('autoexec.be')
|
|
||||||
if s == true
|
|
||||||
var jm = string.format("{\"nlui_driver_update\":\"%s\"}", "succeeded")
|
|
||||||
tasmota.publish_result(jm, "RESULT")
|
|
||||||
else
|
|
||||||
var jm = string.format("{\"nlui_driver_update\":\"%s\"}", "failed")
|
|
||||||
tasmota.publish_result(jm, "RESULT")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tasmota.set_timer(0,task)
|
|
||||||
tasmota.resp_cmnd_done()
|
|
||||||
end
|
|
||||||
|
|
||||||
tasmota.add_cmd('UpdateDriverVersion', update_berry_driver)
|
|
||||||
|
|
||||||
def flash_nextion(cmd, idx, payload, payload_json)
|
|
||||||
def task()
|
|
||||||
nextion.flash_nextion(payload)
|
|
||||||
end
|
|
||||||
tasmota.set_timer(0,task)
|
|
||||||
tasmota.resp_cmnd_done()
|
|
||||||
end
|
|
||||||
|
|
||||||
def send_cmd(cmd, idx, payload, payload_json)
|
|
||||||
nextion.sendnx(payload)
|
|
||||||
tasmota.resp_cmnd_done()
|
|
||||||
end
|
|
||||||
|
|
||||||
def send_cmd2(cmd, idx, payload, payload_json)
|
|
||||||
nextion.send(payload)
|
|
||||||
tasmota.resp_cmnd_done()
|
|
||||||
end
|
|
||||||
|
|
||||||
tasmota.add_cmd('Nextion', send_cmd)
|
|
||||||
tasmota.add_cmd('CustomSend', send_cmd2)
|
|
||||||
tasmota.add_cmd('FlashNextion', flash_nextion)
|
|
||||||
409
tasmota/autoexec-legacy-range.be
Normal file
409
tasmota/autoexec-legacy-range.be
Normal file
@@ -0,0 +1,409 @@
|
|||||||
|
# Nextion Serial Protocol driver by joBr99 + nextion upload protocol 1.2 (the fast one yay) implementation using http range and tcpclient
|
||||||
|
# based on;
|
||||||
|
# Sonoff NSPanel Tasmota driver v0.47 | code by blakadder and s-hadinger
|
||||||
|
|
||||||
|
class TftDownloader
|
||||||
|
var tcp
|
||||||
|
|
||||||
|
var host
|
||||||
|
var port
|
||||||
|
var file
|
||||||
|
|
||||||
|
var s
|
||||||
|
var b
|
||||||
|
var tft_file_size
|
||||||
|
var current_chunk
|
||||||
|
var current_chunk_start
|
||||||
|
var download_range
|
||||||
|
|
||||||
|
|
||||||
|
def init(host, port, file, download_range)
|
||||||
|
self.tft_file_size = 0
|
||||||
|
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.file = file
|
||||||
|
self.download_range = download_range #32768
|
||||||
|
end
|
||||||
|
|
||||||
|
def download_chunk(b_start, b_length)
|
||||||
|
import string
|
||||||
|
self.tcp = tcpclient()
|
||||||
|
self.tcp.connect(self.host, self.port)
|
||||||
|
print("connected:", self.tcp.connected())
|
||||||
|
self.s = "GET " + self.file + " HTTP/1.0\r\n"
|
||||||
|
self.s += "HOST: " + self.host + "\r\n"
|
||||||
|
self.s += string.format("Range: bytes=%d-%d\r\n", b_start, (b_start+b_length-1))
|
||||||
|
print(string.format("Downloading Byte %d - %d", b_start, (b_start+b_length-1)))
|
||||||
|
self.s += "\r\n"
|
||||||
|
self.tcp.write(self.s)
|
||||||
|
|
||||||
|
#read one char after another until we reached end of http header
|
||||||
|
var end_of_header = false
|
||||||
|
var header = ""
|
||||||
|
while !end_of_header
|
||||||
|
if self.tcp.available() > 0
|
||||||
|
header += self.tcp.read(1)
|
||||||
|
if(string.find(header, '\r\n\r\n') != -1)
|
||||||
|
end_of_header = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
var content_length = 0
|
||||||
|
|
||||||
|
# check for 206 status code
|
||||||
|
if(string.find(header, '206 Partial Content') != -1)
|
||||||
|
# download was sucessful
|
||||||
|
else
|
||||||
|
print("Error while downloading")
|
||||||
|
print(header)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# convert header to list
|
||||||
|
header = string.split(header, '\r\n')
|
||||||
|
for i : header.iter()
|
||||||
|
#print(i)
|
||||||
|
if(string.find(i, 'Content-Range:') != -1)
|
||||||
|
if self.tft_file_size == 0
|
||||||
|
print(i)
|
||||||
|
self.tft_file_size = number(string.split(i, '/')[1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if(string.find(i, 'Content-Length:') != -1)
|
||||||
|
content_length = number(string.split(i, 16)[1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#print(content_length)
|
||||||
|
# read bytes until content_length is reached
|
||||||
|
var content = bytes()
|
||||||
|
while content.size() != content_length
|
||||||
|
if self.tcp.available() > 0
|
||||||
|
content += self.tcp.readbytes()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
#print(content.size())
|
||||||
|
return content
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_file_size()
|
||||||
|
self.download_chunk(0, 1)
|
||||||
|
return self.tft_file_size
|
||||||
|
end
|
||||||
|
|
||||||
|
# returns the next 4096 bytes after pos of the tft file
|
||||||
|
def next_chunk(pos)
|
||||||
|
if(self.current_chunk == nil)
|
||||||
|
print("current chunk empty")
|
||||||
|
self.current_chunk = self.download_chunk(pos, self.download_range)
|
||||||
|
self.current_chunk_start = pos
|
||||||
|
end
|
||||||
|
if(pos < self.current_chunk_start)
|
||||||
|
print("Requested pos is below start point of chunk in memory, not implemented")
|
||||||
|
end
|
||||||
|
if(pos >= (self.current_chunk_start+self.download_range))
|
||||||
|
print("Requested pos is after the end of chunk in memory, downloading new range")
|
||||||
|
self.current_chunk = self.download_chunk(pos, self.download_range)
|
||||||
|
self.current_chunk_start = pos
|
||||||
|
end
|
||||||
|
var start_within_current_chunk = pos - self.current_chunk_start
|
||||||
|
return self.current_chunk[start_within_current_chunk..(start_within_current_chunk+4095)]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Nextion : Driver
|
||||||
|
|
||||||
|
var ser
|
||||||
|
var flash_size
|
||||||
|
var flash_mode
|
||||||
|
var flash_version
|
||||||
|
var flash_skip
|
||||||
|
var flash_current_byte
|
||||||
|
var tftd
|
||||||
|
var progress_percentage_last
|
||||||
|
static header = bytes('55BB')
|
||||||
|
|
||||||
|
def init()
|
||||||
|
log("NSP: Initializing Driver")
|
||||||
|
self.ser = serial(17, 16, 115200, serial.SERIAL_8N1)
|
||||||
|
self.flash_mode = 0
|
||||||
|
self.flash_version = 1
|
||||||
|
self.flash_skip = false
|
||||||
|
tasmota.add_driver(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def crc16(data, poly)
|
||||||
|
if !poly poly = 0xA001 end
|
||||||
|
# CRC-16 MODBUS HASHING ALGORITHM
|
||||||
|
var crc = 0xFFFF
|
||||||
|
for i:0..size(data)-1
|
||||||
|
crc = crc ^ data[i]
|
||||||
|
for j:0..7
|
||||||
|
if crc & 1
|
||||||
|
crc = (crc >> 1) ^ poly
|
||||||
|
else
|
||||||
|
crc = crc >> 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return crc
|
||||||
|
end
|
||||||
|
|
||||||
|
def split_55(b)
|
||||||
|
var ret = []
|
||||||
|
var s = size(b)
|
||||||
|
var i = s-2 # start from last-1
|
||||||
|
while i > 0
|
||||||
|
if b[i] == 0x55 && b[i+1] == 0xBB
|
||||||
|
ret.push(b[i..s-1]) # push last msg to list
|
||||||
|
b = b[(0..i-1)] # write the rest back to b
|
||||||
|
end
|
||||||
|
i -= 1
|
||||||
|
end
|
||||||
|
ret.push(b)
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
# encode using custom protocol 55 BB [payload length] [payload length] [payload] [crc] [crc]
|
||||||
|
def encode(payload)
|
||||||
|
var b = bytes()
|
||||||
|
b += self.header
|
||||||
|
b.add(size(payload), 2) # add size as 2 bytes, little endian
|
||||||
|
b += bytes().fromstring(payload)
|
||||||
|
var msg_crc = self.crc16(b)
|
||||||
|
b.add(msg_crc, 2) # crc 2 bytes, little endian
|
||||||
|
return b
|
||||||
|
end
|
||||||
|
|
||||||
|
# send a nextion payload
|
||||||
|
def encodenx(payload)
|
||||||
|
var b = bytes().fromstring(payload)
|
||||||
|
b += bytes('FFFFFF')
|
||||||
|
return b
|
||||||
|
end
|
||||||
|
|
||||||
|
def sendnx(payload)
|
||||||
|
var payload_bin = self.encodenx(payload)
|
||||||
|
self.ser.write(payload_bin)
|
||||||
|
print("NSP: Sent =", payload_bin)
|
||||||
|
log("NSP: Nextion command sent = " + str(payload_bin), 3)
|
||||||
|
end
|
||||||
|
|
||||||
|
def send(payload)
|
||||||
|
var payload_bin = self.encode(payload)
|
||||||
|
if self.flash_mode==1
|
||||||
|
log("NSP: skipped command becuase still flashing", 3)
|
||||||
|
else
|
||||||
|
self.ser.write(payload_bin)
|
||||||
|
log("NSP: payload sent = " + str(payload_bin), 3)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def start_flash(url)
|
||||||
|
import string
|
||||||
|
var host
|
||||||
|
var port
|
||||||
|
var s1 = string.split(url,7)[1]
|
||||||
|
var i = string.find(s1,":")
|
||||||
|
var sa
|
||||||
|
if i<0
|
||||||
|
port = 80
|
||||||
|
i = string.find(s1,"/")
|
||||||
|
sa = string.split(s1,i)
|
||||||
|
host = sa[0]
|
||||||
|
else
|
||||||
|
sa = string.split(s1,i)
|
||||||
|
host = sa[0]
|
||||||
|
s1 = string.split(sa[1],1)[1]
|
||||||
|
i = string.find(s1,"/")
|
||||||
|
sa = string.split(s1,i)
|
||||||
|
port = int(sa[0])
|
||||||
|
end
|
||||||
|
var file = sa[1]
|
||||||
|
#print(host,port,file)
|
||||||
|
|
||||||
|
self.tftd = TftDownloader(host, port, file, 32768)
|
||||||
|
|
||||||
|
# get size of tft file
|
||||||
|
self.flash_size = self.tftd.get_file_size()
|
||||||
|
|
||||||
|
self.flash_mode = 1
|
||||||
|
self.sendnx('DRAKJHSUYDGBNCJHGJKSHBDN')
|
||||||
|
self.sendnx('recmod=0')
|
||||||
|
self.sendnx('recmod=0')
|
||||||
|
self.sendnx("connect")
|
||||||
|
self.sendnx("connect")
|
||||||
|
|
||||||
|
self.flash_current_byte = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_chunk(b_start)
|
||||||
|
var chunk = self.tftd.next_chunk(b_start)
|
||||||
|
#import string
|
||||||
|
#print(string.format("Sending Byte %d - %d with size of %d", b_start, b_start+4095, chunk.size()))
|
||||||
|
self.ser.write(chunk)
|
||||||
|
return chunk.size()
|
||||||
|
end
|
||||||
|
|
||||||
|
def flash_nextion()
|
||||||
|
import string
|
||||||
|
var x = self.write_chunk(self.flash_current_byte)
|
||||||
|
self.flash_current_byte = self.flash_current_byte + x
|
||||||
|
var progress_percentage = (self.flash_current_byte*100/self.flash_size)
|
||||||
|
if (self.progress_percentage_last!=progress_percentage)
|
||||||
|
print(string.format("Flashing Progress ( %d / %d ) [ %d ]", self.flash_current_byte, self.flash_size, progress_percentage))
|
||||||
|
self.progress_percentage_last = progress_percentage
|
||||||
|
tasmota.publish_result(string.format("{\"Flashing\":{\"complete\": %d}}",progress_percentage), "RESULT")
|
||||||
|
end
|
||||||
|
if (self.flash_current_byte==self.flash_size)
|
||||||
|
log("NSP: Flashing complete")
|
||||||
|
self.flash_mode = 0
|
||||||
|
end
|
||||||
|
tasmota.yield()
|
||||||
|
end
|
||||||
|
|
||||||
|
def every_100ms()
|
||||||
|
import string
|
||||||
|
if self.ser.available() > 0
|
||||||
|
var msg = self.ser.read()
|
||||||
|
if size(msg) > 0
|
||||||
|
print("NSP: Received Raw =", msg)
|
||||||
|
if self.flash_mode==1
|
||||||
|
var str = msg[0..-4].asstring()
|
||||||
|
log(str, 3)
|
||||||
|
# TODO: add check for firmware versions < 126 and send proto 1.1 command for thoose
|
||||||
|
if (string.find(str,"comok 2")==0)
|
||||||
|
if self.flash_version==1
|
||||||
|
log("NSP: Flashing 1.1")
|
||||||
|
self.sendnx(string.format("whmi-wri %d,115200,1",self.flash_size)) # Nextion Upload Protocol 1.1
|
||||||
|
else
|
||||||
|
log("NSP: Flashing 1.2")
|
||||||
|
self.sendnx(string.format("whmi-wris %d,115200,1",self.flash_size)) # Nextion Upload Protocol 1.2
|
||||||
|
end
|
||||||
|
|
||||||
|
# skip to byte (upload protocol 1.2)
|
||||||
|
elif (size(msg)==1 && msg[0]==0x08)
|
||||||
|
self.flash_skip = true
|
||||||
|
print("rec 0x08")
|
||||||
|
elif (size(msg)==4 && self.flash_skip)
|
||||||
|
var skip_to_byte = msg[0..4].get(0,4)
|
||||||
|
if(skip_to_byte == 0)
|
||||||
|
print("don't skip, offset is 0")
|
||||||
|
else
|
||||||
|
print("skip to ", skip_to_byte)
|
||||||
|
self.flash_current_byte = skip_to_byte
|
||||||
|
end
|
||||||
|
self.flash_nextion()
|
||||||
|
# send next 4096 bytes (proto 1.1/1.2)
|
||||||
|
elif (size(msg)==1 && msg[0]==0x05)
|
||||||
|
print("rec 0x05")
|
||||||
|
self.flash_nextion()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
# Recive messages using custom protocol 55 BB [payload length] [payload length] [payload] [crc] [crc]
|
||||||
|
if msg[0..1] == self.header
|
||||||
|
var lst = self.split_55(msg)
|
||||||
|
for i:0..size(lst)-1
|
||||||
|
msg = lst[i]
|
||||||
|
#var j = msg[2]+2
|
||||||
|
var j = size(msg) - 3
|
||||||
|
msg = msg[4..j]
|
||||||
|
if size(msg) > 2
|
||||||
|
var jm = string.format("{\"CustomRecv\":\"%s\"}",msg.asstring())
|
||||||
|
tasmota.publish_result(jm, "RESULT")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elif msg == bytes('000000FFFFFF88FFFFFF')
|
||||||
|
log("NSP: Screen Initialized")
|
||||||
|
else
|
||||||
|
var jm = string.format("{\"nextion\":\"%s\"}",str(msg[0..-4]))
|
||||||
|
tasmota.publish_result(jm, "RESULT")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_current_version(cmd, idx, payload, payload_json)
|
||||||
|
import string
|
||||||
|
var version_of_this_script = 2
|
||||||
|
var jm = string.format("{\"nlui_driver_version\":\"%s\"}", version_of_this_script)
|
||||||
|
tasmota.publish_result(jm, "RESULT")
|
||||||
|
end
|
||||||
|
|
||||||
|
tasmota.add_cmd('GetDriverVersion', get_current_version)
|
||||||
|
|
||||||
|
def update_berry_driver(cmd, idx, payload, payload_json)
|
||||||
|
def task()
|
||||||
|
import string
|
||||||
|
var cl = webclient()
|
||||||
|
cl.begin(payload)
|
||||||
|
var r = cl.GET()
|
||||||
|
if r == 200
|
||||||
|
print("Sucessfully downloaded nspanel-lovelace-ui berry driver")
|
||||||
|
else
|
||||||
|
print("Error while downloading nspanel-lovelace-ui berry driver")
|
||||||
|
end
|
||||||
|
r = cl.write_file("autoexec.be")
|
||||||
|
if r < 0
|
||||||
|
print("Error while writeing nspanel-lovelace-ui berry driver")
|
||||||
|
else
|
||||||
|
print("Scucessfully written nspanel-lovelace-ui berry driver")
|
||||||
|
var s = load('autoexec.be')
|
||||||
|
if s == true
|
||||||
|
var jm = string.format("{\"nlui_driver_update\":\"%s\"}", "succeeded")
|
||||||
|
tasmota.publish_result(jm, "RESULT")
|
||||||
|
else
|
||||||
|
var jm = string.format("{\"nlui_driver_update\":\"%s\"}", "failed")
|
||||||
|
tasmota.publish_result(jm, "RESULT")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
tasmota.set_timer(0,task)
|
||||||
|
tasmota.resp_cmnd_done()
|
||||||
|
end
|
||||||
|
|
||||||
|
tasmota.add_cmd('UpdateDriverVersion', update_berry_driver)
|
||||||
|
|
||||||
|
var nextion = Nextion()
|
||||||
|
|
||||||
|
def flash_nextion(cmd, idx, payload, payload_json)
|
||||||
|
def task()
|
||||||
|
nextion.flash_version = 1
|
||||||
|
nextion.start_flash(payload)
|
||||||
|
end
|
||||||
|
tasmota.set_timer(0,task)
|
||||||
|
tasmota.resp_cmnd_done()
|
||||||
|
end
|
||||||
|
|
||||||
|
tasmota.add_cmd('FlashNextion', flash_nextion)
|
||||||
|
|
||||||
|
def flash_nextion_1_2(cmd, idx, payload, payload_json)
|
||||||
|
def task()
|
||||||
|
nextion.flash_version = 2
|
||||||
|
nextion.start_flash(payload)
|
||||||
|
end
|
||||||
|
tasmota.set_timer(0,task)
|
||||||
|
tasmota.resp_cmnd_done()
|
||||||
|
end
|
||||||
|
|
||||||
|
tasmota.add_cmd('FlashNextionFast', flash_nextion_1_2)
|
||||||
|
|
||||||
|
def send_cmd(cmd, idx, payload, payload_json)
|
||||||
|
nextion.sendnx(payload)
|
||||||
|
tasmota.resp_cmnd_done()
|
||||||
|
end
|
||||||
|
|
||||||
|
tasmota.add_cmd('Nextion', send_cmd)
|
||||||
|
|
||||||
|
def send_cmd2(cmd, idx, payload, payload_json)
|
||||||
|
nextion.send(payload)
|
||||||
|
tasmota.resp_cmnd_done()
|
||||||
|
end
|
||||||
|
|
||||||
|
tasmota.add_cmd('CustomSend', send_cmd2)
|
||||||
@@ -1,138 +1,43 @@
|
|||||||
# Nextion Serial Protocol driver by joBr99 + nextion upload protocol 1.2 (the fast one yay) implementation using http range and tcpclient
|
# Sonoff NSPanel Tasmota Lovelace UI Berry Driver | code by joBr99
|
||||||
|
# based on;
|
||||||
|
# Sonoff NSPanel Tasmota (Nextion with Flashing) driver | code by peepshow-21
|
||||||
# based on;
|
# based on;
|
||||||
# Sonoff NSPanel Tasmota driver v0.47 | code by blakadder and s-hadinger
|
# Sonoff NSPanel Tasmota driver v0.47 | code by blakadder and s-hadinger
|
||||||
|
|
||||||
class TftDownloader
|
# Example Flash
|
||||||
var tcp
|
# FlashNextion http://ip-address-of-your-homeassistant:8123/local/nspanel.tft
|
||||||
|
# FlashNextion http://nspanel.pky.eu/lui.tft
|
||||||
var host
|
|
||||||
var port
|
|
||||||
var file
|
|
||||||
|
|
||||||
var s
|
|
||||||
var b
|
|
||||||
var tft_file_size
|
|
||||||
var current_chunk
|
|
||||||
var current_chunk_start
|
|
||||||
var download_range
|
|
||||||
|
|
||||||
|
|
||||||
def init(host, port, file, download_range)
|
|
||||||
self.tft_file_size = 0
|
|
||||||
|
|
||||||
self.host = host
|
|
||||||
self.port = port
|
|
||||||
self.file = file
|
|
||||||
self.download_range = download_range #32768
|
|
||||||
end
|
|
||||||
|
|
||||||
def download_chunk(b_start, b_length)
|
|
||||||
import string
|
|
||||||
self.tcp = tcpclient()
|
|
||||||
self.tcp.connect(self.host, self.port)
|
|
||||||
print("connected:", self.tcp.connected())
|
|
||||||
self.s = "GET " + self.file + " HTTP/1.0\r\n"
|
|
||||||
self.s += "HOST: " + self.host + "\r\n"
|
|
||||||
self.s += string.format("Range: bytes=%d-%d\r\n", b_start, (b_start+b_length-1))
|
|
||||||
print(string.format("Downloading Byte %d - %d", b_start, (b_start+b_length-1)))
|
|
||||||
self.s += "\r\n"
|
|
||||||
self.tcp.write(self.s)
|
|
||||||
|
|
||||||
#read one char after another until we reached end of http header
|
|
||||||
var end_of_header = false
|
|
||||||
var header = ""
|
|
||||||
while !end_of_header
|
|
||||||
if self.tcp.available() > 0
|
|
||||||
header += self.tcp.read(1)
|
|
||||||
if(string.find(header, '\r\n\r\n') != -1)
|
|
||||||
end_of_header = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
var content_length = 0
|
|
||||||
|
|
||||||
# check for 206 status code
|
|
||||||
if(string.find(header, '206 Partial Content') != -1)
|
|
||||||
# download was sucessful
|
|
||||||
else
|
|
||||||
print("Error while downloading")
|
|
||||||
print(header)
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
# convert header to list
|
|
||||||
header = string.split(header, '\r\n')
|
|
||||||
for i : header.iter()
|
|
||||||
#print(i)
|
|
||||||
if(string.find(i, 'Content-Range:') != -1)
|
|
||||||
if self.tft_file_size == 0
|
|
||||||
print(i)
|
|
||||||
self.tft_file_size = number(string.split(i, '/')[1])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if(string.find(i, 'Content-Length:') != -1)
|
|
||||||
content_length = number(string.split(i, 16)[1])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
#print(content_length)
|
|
||||||
# read bytes until content_length is reached
|
|
||||||
var content = bytes()
|
|
||||||
while content.size() != content_length
|
|
||||||
if self.tcp.available() > 0
|
|
||||||
content += self.tcp.readbytes()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
#print(content.size())
|
|
||||||
return content
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_file_size()
|
|
||||||
self.download_chunk(0, 1)
|
|
||||||
return self.tft_file_size
|
|
||||||
end
|
|
||||||
|
|
||||||
# returns the next 4096 bytes after pos of the tft file
|
|
||||||
def next_chunk(pos)
|
|
||||||
if(self.current_chunk == nil)
|
|
||||||
print("current chunk empty")
|
|
||||||
self.current_chunk = self.download_chunk(pos, self.download_range)
|
|
||||||
self.current_chunk_start = pos
|
|
||||||
end
|
|
||||||
if(pos < self.current_chunk_start)
|
|
||||||
print("Requested pos is below start point of chunk in memory, not implemented")
|
|
||||||
end
|
|
||||||
if(pos >= (self.current_chunk_start+self.download_range))
|
|
||||||
print("Requested pos is after the end of chunk in memory, downloading new range")
|
|
||||||
self.current_chunk = self.download_chunk(pos, self.download_range)
|
|
||||||
self.current_chunk_start = pos
|
|
||||||
end
|
|
||||||
var start_within_current_chunk = pos - self.current_chunk_start
|
|
||||||
return self.current_chunk[start_within_current_chunk..(start_within_current_chunk+4095)]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Nextion : Driver
|
class Nextion : Driver
|
||||||
|
|
||||||
var ser
|
static VERSION = "1.1.3"
|
||||||
var flash_size
|
static header = bytes('55BB')
|
||||||
var flash_mode
|
|
||||||
var flash_version
|
|
||||||
var flash_skip
|
|
||||||
var flash_current_byte
|
|
||||||
var tftd
|
|
||||||
var progress_percentage_last
|
|
||||||
static header = bytes('55BB')
|
|
||||||
|
|
||||||
def init()
|
static flash_block_size = 4096
|
||||||
log("NSP: Initializing Driver")
|
|
||||||
self.ser = serial(17, 16, 115200, serial.SERIAL_8N1)
|
var flash_mode
|
||||||
self.flash_mode = 0
|
var flash_size
|
||||||
self.flash_version = 1
|
var flash_written
|
||||||
self.flash_skip = false
|
var flash_buff
|
||||||
tasmota.add_driver(self)
|
var flash_offset
|
||||||
|
var awaiting_offset
|
||||||
|
var tcp
|
||||||
|
var ser
|
||||||
|
var last_per
|
||||||
|
|
||||||
|
def split_55(b)
|
||||||
|
var ret = []
|
||||||
|
var s = size(b)
|
||||||
|
var i = s-2 # start from last-1
|
||||||
|
while i > 0
|
||||||
|
if b[i] == 0x55 && b[i+1] == 0xBB
|
||||||
|
ret.push(b[i..s-1]) # push last msg to list
|
||||||
|
b = b[(0..i-1)] # write the rest back to b
|
||||||
|
end
|
||||||
|
i -= 1
|
||||||
|
end
|
||||||
|
ret.push(b)
|
||||||
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
def crc16(data, poly)
|
def crc16(data, poly)
|
||||||
@@ -152,21 +57,6 @@ class Nextion : Driver
|
|||||||
return crc
|
return crc
|
||||||
end
|
end
|
||||||
|
|
||||||
def split_55(b)
|
|
||||||
var ret = []
|
|
||||||
var s = size(b)
|
|
||||||
var i = s-2 # start from last-1
|
|
||||||
while i > 0
|
|
||||||
if b[i] == 0x55 && b[i+1] == 0xBB
|
|
||||||
ret.push(b[i..s-1]) # push last msg to list
|
|
||||||
b = b[(0..i-1)] # write the rest back to b
|
|
||||||
end
|
|
||||||
i -= 1
|
|
||||||
end
|
|
||||||
ret.push(b)
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
# encode using custom protocol 55 BB [payload length] [payload length] [payload] [crc] [crc]
|
# encode using custom protocol 55 BB [payload length] [payload length] [payload] [crc] [crc]
|
||||||
def encode(payload)
|
def encode(payload)
|
||||||
var b = bytes()
|
var b = bytes()
|
||||||
@@ -178,32 +68,143 @@ class Nextion : Driver
|
|||||||
return b
|
return b
|
||||||
end
|
end
|
||||||
|
|
||||||
# send a nextion payload
|
def encodenx(payload)
|
||||||
def encodenx(payload)
|
var b = bytes().fromstring(payload)
|
||||||
var b = bytes().fromstring(payload)
|
b += bytes('FFFFFF')
|
||||||
b += bytes('FFFFFF')
|
return b
|
||||||
return b
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def sendnx(payload)
|
def sendnx(payload)
|
||||||
var payload_bin = self.encodenx(payload)
|
import string
|
||||||
self.ser.write(payload_bin)
|
var payload_bin = self.encodenx(payload)
|
||||||
print("NSP: Sent =", payload_bin)
|
self.ser.write(payload_bin)
|
||||||
log("NSP: Nextion command sent = " + str(payload_bin), 3)
|
log(string.format("NXP: Nextion command sent = %s",str(payload_bin)), 3)
|
||||||
end
|
end
|
||||||
|
|
||||||
def send(payload)
|
def send(payload)
|
||||||
var payload_bin = self.encode(payload)
|
var payload_bin = self.encode(payload)
|
||||||
if self.flash_mode==1
|
if self.flash_mode==1
|
||||||
log("NSP: skipped command becuase still flashing", 3)
|
log("NXP: skipped command becuase still flashing", 3)
|
||||||
else
|
else
|
||||||
self.ser.write(payload_bin)
|
self.ser.write(payload_bin)
|
||||||
log("NSP: payload sent = " + str(payload_bin), 3)
|
log("NXP: payload sent = " + str(payload_bin), 3)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def start_flash(url)
|
def write_to_nextion(b)
|
||||||
import string
|
self.ser.write(b)
|
||||||
|
end
|
||||||
|
|
||||||
|
def screeninit()
|
||||||
|
log("NXP: Screen Initialized")
|
||||||
|
self.sendnx("recmod=1")
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_block()
|
||||||
|
|
||||||
|
import string
|
||||||
|
log("FLH: Read block",3)
|
||||||
|
while size(self.flash_buff)<self.flash_block_size && self.tcp.connected()
|
||||||
|
if self.tcp.available()>0
|
||||||
|
self.flash_buff += self.tcp.readbytes()
|
||||||
|
else
|
||||||
|
tasmota.delay(50)
|
||||||
|
log("FLH: Wait for available...",3)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
log("FLH: Buff size "+str(size(self.flash_buff)),3)
|
||||||
|
var to_write
|
||||||
|
if size(self.flash_buff)>self.flash_block_size
|
||||||
|
to_write = self.flash_buff[0..self.flash_block_size-1]
|
||||||
|
self.flash_buff = self.flash_buff[self.flash_block_size..]
|
||||||
|
else
|
||||||
|
to_write = self.flash_buff
|
||||||
|
self.flash_buff = bytes()
|
||||||
|
end
|
||||||
|
log("FLH: Writing "+str(size(to_write)),3)
|
||||||
|
var per = (self.flash_written*100)/self.flash_size
|
||||||
|
if (self.last_per!=per)
|
||||||
|
self.last_per = per
|
||||||
|
tasmota.publish_result(string.format("{\"Flashing\":{\"complete\": %d}}",per), "RESULT")
|
||||||
|
end
|
||||||
|
if size(to_write)>0
|
||||||
|
self.flash_written += size(to_write)
|
||||||
|
if self.flash_offset==0 || self.flash_written>self.flash_offset
|
||||||
|
self.ser.write(to_write)
|
||||||
|
self.flash_offset = 0
|
||||||
|
else
|
||||||
|
tasmota.set_timer(10,/->self.write_block())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
log("FLH: Total "+str(self.flash_written),3)
|
||||||
|
if (self.flash_written==self.flash_size)
|
||||||
|
log("FLH: Flashing complete")
|
||||||
|
self.flash_mode = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def every_100ms()
|
||||||
|
import string
|
||||||
|
if self.ser.available() > 0
|
||||||
|
var msg = self.ser.read()
|
||||||
|
if size(msg) > 0
|
||||||
|
log(string.format("NXP: Received Raw = %s",str(msg)), 3)
|
||||||
|
if (self.flash_mode==1)
|
||||||
|
var strv = msg[0..-4].asstring()
|
||||||
|
if string.find(strv,"comok 2")>=0
|
||||||
|
log("FLH: Send (High Speed) flash start")
|
||||||
|
self.sendnx(string.format("whmi-wris %d,115200,res0",self.flash_size))
|
||||||
|
elif size(msg)==1 && msg[0]==0x08
|
||||||
|
log("FLH: Waiting offset...",3)
|
||||||
|
self.awaiting_offset = 1
|
||||||
|
elif size(msg)==4 && self.awaiting_offset==1
|
||||||
|
self.awaiting_offset = 0
|
||||||
|
self.flash_offset = msg.get(0,4)
|
||||||
|
log("FLH: Flash offset marker "+str(self.flash_offset),3)
|
||||||
|
self.write_block()
|
||||||
|
elif size(msg)==1 && msg[0]==0x05
|
||||||
|
self.write_block()
|
||||||
|
else
|
||||||
|
log("FLH: Something has gone wrong flashing display firmware ["+str(msg)+"]",2)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
var msg_list = self.split_55(msg)
|
||||||
|
for i:0..size(msg_list)-1
|
||||||
|
msg = msg_list[i]
|
||||||
|
if size(msg) > 0
|
||||||
|
if msg == bytes('000000FFFFFF88FFFFFF')
|
||||||
|
self.screeninit()
|
||||||
|
elif size(msg)>=2 && msg[0]==0x55 && msg[1]==0xBB
|
||||||
|
var jm = string.format("{\"CustomRecv\":\"%s\"}",msg[4..-3].asstring())
|
||||||
|
tasmota.publish_result(jm, "RESULT")
|
||||||
|
elif msg[0]==0x07 && size(msg)==1 # BELL/Buzzer
|
||||||
|
tasmota.cmd("buzzer 1,1")
|
||||||
|
else
|
||||||
|
var jm = string.format("{\"nextion\":\"%s\"}",str(msg[0..-4]))
|
||||||
|
tasmota.publish_result(jm, "RESULT")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def begin_nextion_flash()
|
||||||
|
self.flash_written = 0
|
||||||
|
self.awaiting_offset = 0
|
||||||
|
self.flash_offset = 0
|
||||||
|
self.sendnx('DRAKJHSUYDGBNCJHGJKSHBDN')
|
||||||
|
self.sendnx('recmod=0')
|
||||||
|
self.sendnx('recmod=0')
|
||||||
|
self.flash_mode = 1
|
||||||
|
self.sendnx("connect")
|
||||||
|
end
|
||||||
|
|
||||||
|
def open_url(url)
|
||||||
|
|
||||||
|
import string
|
||||||
var host
|
var host
|
||||||
var port
|
var port
|
||||||
var s1 = string.split(url,7)[1]
|
var s1 = string.split(url,7)[1]
|
||||||
@@ -222,115 +223,109 @@ class Nextion : Driver
|
|||||||
sa = string.split(s1,i)
|
sa = string.split(s1,i)
|
||||||
port = int(sa[0])
|
port = int(sa[0])
|
||||||
end
|
end
|
||||||
var file = sa[1]
|
var get = sa[1]
|
||||||
#print(host,port,file)
|
log(string.format("FLH: host: %s, port: %s, get: %s",host,port,get))
|
||||||
|
self.tcp = tcpclient()
|
||||||
self.tftd = TftDownloader(host, port, file, 32768)
|
self.tcp.connect(host,port)
|
||||||
|
log("FLH: Connected:"+str(self.tcp.connected()),3)
|
||||||
# get size of tft file
|
var get_req = "GET "+get+" HTTP/1.0\r\n"
|
||||||
self.flash_size = self.tftd.get_file_size()
|
get_req += string.format("HOST: %s:%s\r\n\r\n",host,port)
|
||||||
|
self.tcp.write(get_req)
|
||||||
self.flash_mode = 1
|
var a = self.tcp.available()
|
||||||
self.sendnx('DRAKJHSUYDGBNCJHGJKSHBDN')
|
i = 1
|
||||||
self.sendnx('recmod=0')
|
while a==0 && i<5
|
||||||
self.sendnx('recmod=0')
|
tasmota.delay(100*i)
|
||||||
self.sendnx("connect")
|
tasmota.yield()
|
||||||
self.sendnx("connect")
|
i += 1
|
||||||
|
log("FLH: Retry "+str(i),3)
|
||||||
self.flash_current_byte = 0
|
a = self.tcp.available()
|
||||||
end
|
|
||||||
|
|
||||||
def write_chunk(b_start)
|
|
||||||
var chunk = self.tftd.next_chunk(b_start)
|
|
||||||
#import string
|
|
||||||
#print(string.format("Sending Byte %d - %d with size of %d", b_start, b_start+4095, chunk.size()))
|
|
||||||
self.ser.write(chunk)
|
|
||||||
return chunk.size()
|
|
||||||
end
|
|
||||||
|
|
||||||
def flash_nextion()
|
|
||||||
import string
|
|
||||||
var x = self.write_chunk(self.flash_current_byte)
|
|
||||||
self.flash_current_byte = self.flash_current_byte + x
|
|
||||||
var progress_percentage = (self.flash_current_byte*100/self.flash_size)
|
|
||||||
if (self.progress_percentage_last!=progress_percentage)
|
|
||||||
print(string.format("Flashing Progress ( %d / %d ) [ %d ]", self.flash_current_byte, self.flash_size, progress_percentage))
|
|
||||||
self.progress_percentage_last = progress_percentage
|
|
||||||
tasmota.publish_result(string.format("{\"Flashing\":{\"complete\": %d}}",progress_percentage), "RESULT")
|
|
||||||
end
|
end
|
||||||
if (self.flash_current_byte==self.flash_size)
|
if a==0
|
||||||
log("NSP: Flashing complete")
|
log("FLH: Nothing available to read!",3)
|
||||||
self.flash_mode = 0
|
return
|
||||||
end
|
end
|
||||||
tasmota.yield()
|
var b = self.tcp.readbytes()
|
||||||
end
|
i = 0
|
||||||
|
var end_headers = false;
|
||||||
def every_100ms()
|
var headers
|
||||||
import string
|
while i<size(b) && headers==nil
|
||||||
if self.ser.available() > 0
|
if b[i..(i+3)]==bytes().fromstring("\r\n\r\n")
|
||||||
var msg = self.ser.read()
|
headers = b[0..(i+3)].asstring()
|
||||||
if size(msg) > 0
|
self.flash_buff = b[(i+4)..]
|
||||||
print("NSP: Received Raw =", msg)
|
else
|
||||||
if self.flash_mode==1
|
i += 1
|
||||||
var str = msg[0..-4].asstring()
|
|
||||||
log(str, 3)
|
|
||||||
# TODO: add check for firmware versions < 126 and send proto 1.1 command for thoose
|
|
||||||
if (string.find(str,"comok 2")==0)
|
|
||||||
if self.flash_version==1
|
|
||||||
log("NSP: Flashing 1.1")
|
|
||||||
self.sendnx(string.format("whmi-wri %d,115200,1",self.flash_size)) # Nextion Upload Protocol 1.1
|
|
||||||
else
|
|
||||||
log("NSP: Flashing 1.2")
|
|
||||||
self.sendnx(string.format("whmi-wris %d,115200,1",self.flash_size)) # Nextion Upload Protocol 1.2
|
|
||||||
end
|
|
||||||
|
|
||||||
# skip to byte (upload protocol 1.2)
|
|
||||||
elif (size(msg)==1 && msg[0]==0x08)
|
|
||||||
self.flash_skip = true
|
|
||||||
print("rec 0x08")
|
|
||||||
elif (size(msg)==4 && self.flash_skip)
|
|
||||||
var skip_to_byte = msg[0..4].get(0,4)
|
|
||||||
if(skip_to_byte == 0)
|
|
||||||
print("don't skip, offset is 0")
|
|
||||||
else
|
|
||||||
print("skip to ", skip_to_byte)
|
|
||||||
self.flash_current_byte = skip_to_byte
|
|
||||||
end
|
|
||||||
self.flash_nextion()
|
|
||||||
# send next 4096 bytes (proto 1.1/1.2)
|
|
||||||
elif (size(msg)==1 && msg[0]==0x05)
|
|
||||||
print("rec 0x05")
|
|
||||||
self.flash_nextion()
|
|
||||||
end
|
|
||||||
else
|
|
||||||
# Recive messages using custom protocol 55 BB [payload length] [payload length] [payload] [crc] [crc]
|
|
||||||
if msg[0..1] == self.header
|
|
||||||
var lst = self.split_55(msg)
|
|
||||||
for i:0..size(lst)-1
|
|
||||||
msg = lst[i]
|
|
||||||
#var j = msg[2]+2
|
|
||||||
var j = size(msg) - 3
|
|
||||||
msg = msg[4..j]
|
|
||||||
if size(msg) > 2
|
|
||||||
var jm = string.format("{\"CustomRecv\":\"%s\"}",msg.asstring())
|
|
||||||
tasmota.publish_result(jm, "RESULT")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elif msg == bytes('000000FFFFFF88FFFFFF')
|
|
||||||
log("NSP: Screen Initialized")
|
|
||||||
else
|
|
||||||
var jm = string.format("{\"nextion\":\"%s\"}",str(msg[0..-4]))
|
|
||||||
tasmota.publish_result(jm, "RESULT")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
#print(headers)
|
||||||
|
# check http respose for code 200
|
||||||
|
var tag = "200 OK"
|
||||||
|
i = string.find(headers,tag)
|
||||||
|
if (i>0)
|
||||||
|
log("FLH: HTTP Respose is 200 OK",3)
|
||||||
|
else
|
||||||
|
log("FLH: HTTP Respose is not 200 OK",3)
|
||||||
|
print(headers)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
# check http respose for content-length
|
||||||
|
tag = "Content-Length: "
|
||||||
|
i = string.find(headers,tag)
|
||||||
|
if (i>0)
|
||||||
|
var i2 = string.find(headers,"\r\n",i)
|
||||||
|
var s = headers[i+size(tag)..i2-1]
|
||||||
|
self.flash_size=int(s)
|
||||||
|
end
|
||||||
|
if self.flash_size==0
|
||||||
|
log("FLH: No size header, counting ...",3)
|
||||||
|
self.flash_size = size(self.flash_buff)
|
||||||
|
#print("counting start ...")
|
||||||
|
while self.tcp.connected()
|
||||||
|
while self.tcp.available()>0
|
||||||
|
self.flash_size += size(self.tcp.readbytes())
|
||||||
|
end
|
||||||
|
tasmota.delay(50)
|
||||||
|
end
|
||||||
|
#print("counting end ...",self.flash_size)
|
||||||
|
self.tcp.close()
|
||||||
|
self.open_url(url)
|
||||||
|
else
|
||||||
|
log("FLH: Size found in header, skip count",3)
|
||||||
|
end
|
||||||
|
log("FLH: Flash file size: "+str(self.flash_size),3)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def flash_nextion(url)
|
||||||
|
|
||||||
|
self.flash_size = 0
|
||||||
|
self.open_url(url)
|
||||||
|
self.begin_nextion_flash()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def version_number(str)
|
||||||
|
import string
|
||||||
|
var i1 = string.find(str,".",0)
|
||||||
|
var i2 = string.find(str,".",i1+1)
|
||||||
|
var num = int(str[0..i1-1])*10000+int(str[i1+1..i2-1])*100+int(str[i2+1..])
|
||||||
|
return num
|
||||||
|
end
|
||||||
|
|
||||||
|
def init()
|
||||||
|
log("NXP: Initializing Driver")
|
||||||
|
self.ser = serial(17, 16, 115200, serial.SERIAL_8N1)
|
||||||
|
self.flash_mode = 0
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
var nextion = Nextion()
|
||||||
|
|
||||||
|
tasmota.add_driver(nextion)
|
||||||
|
|
||||||
def get_current_version(cmd, idx, payload, payload_json)
|
def get_current_version(cmd, idx, payload, payload_json)
|
||||||
import string
|
import string
|
||||||
var version_of_this_script = 2
|
var version_of_this_script = 3
|
||||||
var jm = string.format("{\"nlui_driver_version\":\"%s\"}", version_of_this_script)
|
var jm = string.format("{\"nlui_driver_version\":\"%s\"}", version_of_this_script)
|
||||||
tasmota.publish_result(jm, "RESULT")
|
tasmota.publish_result(jm, "RESULT")
|
||||||
end
|
end
|
||||||
@@ -352,7 +347,7 @@ def update_berry_driver(cmd, idx, payload, payload_json)
|
|||||||
if r < 0
|
if r < 0
|
||||||
print("Error while writeing nspanel-lovelace-ui berry driver")
|
print("Error while writeing nspanel-lovelace-ui berry driver")
|
||||||
else
|
else
|
||||||
print("Scucessfully written nspanel-lovelace-ui berry driver")
|
print("Sucessfully written nspanel-lovelace-ui berry driver")
|
||||||
var s = load('autoexec.be')
|
var s = load('autoexec.be')
|
||||||
if s == true
|
if s == true
|
||||||
var jm = string.format("{\"nlui_driver_update\":\"%s\"}", "succeeded")
|
var jm = string.format("{\"nlui_driver_update\":\"%s\"}", "succeeded")
|
||||||
@@ -370,40 +365,24 @@ end
|
|||||||
|
|
||||||
tasmota.add_cmd('UpdateDriverVersion', update_berry_driver)
|
tasmota.add_cmd('UpdateDriverVersion', update_berry_driver)
|
||||||
|
|
||||||
var nextion = Nextion()
|
|
||||||
|
|
||||||
def flash_nextion(cmd, idx, payload, payload_json)
|
def flash_nextion(cmd, idx, payload, payload_json)
|
||||||
def task()
|
def task()
|
||||||
nextion.flash_version = 1
|
nextion.flash_nextion(payload)
|
||||||
nextion.start_flash(payload)
|
|
||||||
end
|
end
|
||||||
tasmota.set_timer(0,task)
|
tasmota.set_timer(0,task)
|
||||||
tasmota.resp_cmnd_done()
|
tasmota.resp_cmnd_done()
|
||||||
end
|
end
|
||||||
|
|
||||||
tasmota.add_cmd('FlashNextion', flash_nextion)
|
|
||||||
|
|
||||||
def flash_nextion_1_2(cmd, idx, payload, payload_json)
|
|
||||||
def task()
|
|
||||||
nextion.flash_version = 2
|
|
||||||
nextion.start_flash(payload)
|
|
||||||
end
|
|
||||||
tasmota.set_timer(0,task)
|
|
||||||
tasmota.resp_cmnd_done()
|
|
||||||
end
|
|
||||||
|
|
||||||
tasmota.add_cmd('FlashNextionFast', flash_nextion_1_2)
|
|
||||||
|
|
||||||
def send_cmd(cmd, idx, payload, payload_json)
|
def send_cmd(cmd, idx, payload, payload_json)
|
||||||
nextion.sendnx(payload)
|
nextion.sendnx(payload)
|
||||||
tasmota.resp_cmnd_done()
|
tasmota.resp_cmnd_done()
|
||||||
end
|
end
|
||||||
|
|
||||||
tasmota.add_cmd('Nextion', send_cmd)
|
|
||||||
|
|
||||||
def send_cmd2(cmd, idx, payload, payload_json)
|
def send_cmd2(cmd, idx, payload, payload_json)
|
||||||
nextion.send(payload)
|
nextion.send(payload)
|
||||||
tasmota.resp_cmnd_done()
|
tasmota.resp_cmnd_done()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
tasmota.add_cmd('Nextion', send_cmd)
|
||||||
tasmota.add_cmd('CustomSend', send_cmd2)
|
tasmota.add_cmd('CustomSend', send_cmd2)
|
||||||
|
tasmota.add_cmd('FlashNextion', flash_nextion)
|
||||||
|
|||||||
Reference in New Issue
Block a user