Sonoff NSPanel by ITead - Smart Scene Wall Switch based on ESP32 and custom Nextion Touch Screen Panel Display (non-Pro variant)

Hi all,

Wondering if anyone has come across this issue.

I’ve flashed the panel successfully with ESPHome but it refuses to connect to my WiFi and the logs show the following:

N.B. I’ve triple checked my WiFi credentials and they’re correct.

[15:12:38][I][wifi:245]: WiFi Connecting to 'SKY9316C_home'...
[15:12:39][W][wifi_esp32:495]: Event: Disconnected ssid='SKY9316C_home' bssid=1C:3B:F3:47:6A:7C reason='Auth Expired'
[15:12:39][W][wifi:533]: Error while connecting to network.
[15:12:39][W][wifi:568]: Restarting WiFi adapter...

Here is my ESPHome yaml:

# Set some variables for convenience
substitutions:
  node_name: guest-room-nspanel
  device_name: Guest Room NSPanel
  
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

# Note: this may not be needed if the pull request has been merged.
# Check https://github.com/esphome/esphome/pull/2956 for current status.
external_components:
  - source: github://pr#2956
    components: [nextion]
    refresh: 1h

esphome:
  name: $node_name
  comment: $device_name

esp32:
  board: esp32dev

# Enable logging
logger:

# Enable wireless updates
ota:

# Enable Home Assistant API
api:
  services:
    # Service to play a song
    - service: play_rtttl
      variables:
        song_str: string
      then:
        - rtttl.play:
            rtttl: !lambda 'return song_str;'
    - service: upload_tft
      then:
        - lambda: 'id(disp1)->upload_tft();'

# A reboot button is always useful
button:
  - platform: restart
    name: Restart $device_name

# Define some inputs
binary_sensor:
  - platform: gpio
    name: $device_name Left Button
    pin:
      number: 14
      inverted: true
    on_click:
      - switch.toggle: relay_1

  - platform: gpio
    name: $device_name Right Button
    pin:
      number: 27
      inverted: true
    on_click:
      - switch.toggle: relay_2
  
  - platform: nextion
    name: $device_name Play Button
    page_id: 0
    component_id: 2

  - platform: nextion
    name: $device_name On Button
    page_id: 0
    component_id: 3

  - platform: nextion
    name: $device_name Off Button
    page_id: 0
    component_id: 4

  - platform: nextion
    name: $device_name Red Button
    page_id: 0
    component_id: 6

sensor:
  - platform: wifi_signal
    name: $device_name WiFi Signal
    update_interval: 60s

  - platform: ntc
    id: temperature
    sensor: resistance_sensor
    calibration:
      b_constant: 3950
      reference_temperature: 25°C
      reference_resistance: 10kOhm
    name: $device_name Temperature

  - platform: resistance
    id: resistance_sensor
    sensor: ntc_source
    configuration: DOWNSTREAM
    resistor: 11.2kOhm

  - platform: adc
    id: ntc_source
    pin: 38
    update_interval: 10s
    attenuation: 11db

  # Grab current temperature from Home Assistant
  - platform: homeassistant
    id: current_temperature
    entity_id: weather.home
    attribute: temperature
    on_value:
      # Push it to the display
      then:
        - lambda: 'id(disp1).set_component_text_printf("temp", "%.1f ""\xb0""F", x);'

# Define some outputs
switch:
  # The two relays
  - platform: gpio
    name: $device_name Relay 1
    id: relay_1
    pin:
      number: 22
  - platform: gpio
    name: $device_name Relay 2
    id: relay_2
    pin:
      number: 19

  # Pin 4 always needs to be on to power up the display
  - platform: gpio
    id: screen_power
    entity_category: config
    pin:
      number: 4
      inverted: true
    restore_mode: ALWAYS_ON

number:
  platform: template
  name: $device_name Brightness
  id: brightness
  entity_category: config
  unit_of_measurement: '%'
  min_value: 0
  max_value: 100
  step: 1
  initial_value: 30
  set_action:
    then:
      - lambda: 'id(disp1).set_backlight_brightness(x/100);'

# Configure the internal bleeper
output:
  - platform: ledc
    id: buzzer_out
    pin:
      number: 21

# Enable ringtone music support
rtttl:
  id: buzzer
  output: buzzer_out

# Configure UART for communicating with the screen
uart:
  id: tf_uart
  tx_pin: 16
  rx_pin: 17
  baud_rate: 115200

# Configure the screen itself
display:
  - platform: nextion
    id: disp1
    uart_id: tf_uart
    tft_url: http://192.168.1.101:8123/local/nspanel_demo.tft
    # A little fun...
    on_setup:
      then:
        - number.set:
            id: brightness
            value: 30
        - lambda: |-
            id(disp1).set_component_text_printf(
              "temp", "%.1f ""\xb0""F", id(current_temperature).state
            );
        - rtttl.play: "twobits:d=4,o=5,b=220:c6,8g,8g,a,g,p,b,c6"

Hi Felix,

i’ve updated the config and added the double quotes sadly still no luck

display:
  - platform: nextion
    id: disp1
    uart_id: tf_uart
    tft_url: "http://192.168.1.182:8123/local/nspanel_demo.tft"
    # A little fun...
    on_setup:
      then:
        - number.set:
            id: brightness
            value: 30
        - lambda: |-
            id(disp1).set_component_text_printf(
              "temp", "%.1f ""\xb0""F", id(current_temperature).state
            );
        - rtttl.play: "twobits:d=4,o=5,b=220:c6,8g,8g,a,g,p,b,c6"

Am i missing something else?

Thank you!
Ted

Did you run the upload_tft service on Home Assistant which commands the panel to pul the tft?

Not sure what this means. Is it completely blank? Are you getting any logs?

Yes the screen is completely blank and it doesn’t do the son off startup either

[18:05:56][E][uart:015]: Reading from UART timed out at byte 0!
[18:05:56][W][nextion:078]: Nextion is not connected!

I get this in the console continuously

Ted

Yes I have run the service, these are the logs after I run it

[18:07:27][D][nextion_upload:169]: Connected
[18:07:27][D][nextion_upload:175]: Requesting URL: http://192.168.1.182:8123/local/nspanel_demo.tft
[18:07:28][D][nextion_upload:209]: Updating Nextion ...
[18:07:28][D][nextion_upload:235]: Waiting for upgrade response
[18:07:28][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:28][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:28][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:28][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:28][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:29][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:29][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:29][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:29][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:29][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:29][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:29][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:29][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:29][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:30][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:30][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:30][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:30][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:30][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:30][D][nextion_upload:239]: Upgrade response is  19
[18:07:30][D][nextion_upload:242]: Available 0 : 0x00
[18:07:30][D][nextion_upload:242]: Available 1 : 0x00
[18:07:30][D][nextion_upload:242]: Available 2 : 0x00
[18:07:30][D][nextion_upload:242]: Available 3 : 0x00
[18:07:30][D][nextion_upload:242]: Available 4 : 0x00
[18:07:30][D][nextion_upload:242]: Available 5 : 0x00
[18:07:30][D][nextion_upload:242]: Available 6 : 0x00
[18:07:30][D][nextion_upload:242]: Available 7 : 0x00
[18:07:30][D][nextion_upload:242]: Available 8 : 0x00
[18:07:30][D][nextion_upload:242]: Available 9 : 0x00
[18:07:30][D][nextion_upload:242]: Available 10 : 0x00
[18:07:30][D][nextion_upload:242]: Available 11 : 0x00
[18:07:30][D][nextion_upload:242]: Available 12 : 0x00
[18:07:30][D][nextion_upload:242]: Available 13 : 0x00
[18:07:30][D][nextion_upload:242]: Available 14 : 0x00
[18:07:30][D][nextion_upload:242]: Available 15 : 0x00
[18:07:30][D][nextion_upload:242]: Available 16 : 0x00
[18:07:30][D][nextion_upload:242]: Available 17 : 0x00
[18:07:30][D][nextion_upload:242]: Available 18 : 0x00
[18:07:30][D][nextion_upload:248]: preparation for tft update failed 0 ""
[18:07:30][D][nextion_upload:324]: Restarting Nextion
INFO nspanel-demo.local: Error while reading incoming messages: Error while reading data: [Errno 104] Connection reset by peer
INFO Disconnected from ESPHome API for nspanel-demo.local
WARNING Disconnected from API
INFO nspanel-demo.local: Ping Failed: Error while reading data: [Errno 104] Connection reset by peer
INFO Successfully connected to nspanel-demo.local
[18:07:41][E][uart:015]: Reading from UART timed out at byte 0!
[18:07:41][W][nextion:078]: Nextion is not connected! 

Ted

Ok, if the screen doesn’t even start up, there’s no point in troubleshooting the ability to upload a TFT. Guessing at a few possibilities here:

Random guess #1. It’s not being switched on by the ESP32. GPIO4 controls power to the display, and that needs to be on. If you copied your config from any of the examples, that’s probably not the issue, but it’s worth double checking that you have something like this:

  - platform: gpio
    id: screen_power
    entity_category: config
    pin:
      number: 4
      inverted: true
    restore_mode: ALWAYS_ON

You could also put a name: entry there as well, which will cause it to show up in Home Assistant so you can toggle it off and on and see if anything happens. (E.g. maybe you see a little flicker of activity)

Random guess #2. There’s a problem with the ribbon cable that connects the display to the main board. Other people have had issues when it wasn’t seated properly. Especially if you disconnected it while flashing the thing, it’s worth checking that it’s installed straight in all the way.

How are you powering it? Did you put it back together and hook it up to mains?

A couple of enhancements have been made to the esphome nspanel component. Its been updated to compile against the main branch (so doesn’t need the dev/beta branch)

There is now an “on_json_message” trigger that means the JSON can be parsed with very minimal lambda and YAML based actions initiated.

I have working examples of :
Lamp Widget
RGB Strip Widget
Single socket Widget
Socket group Widget (2 Sockets)
Curtain Widget
Thermostat
Weather Service updates (via wttr.in)

YAML Uploaded to git…GitHub - DeanoXX/esphome-config: Key elements of ESPHome YAML Configs

5 Likes

Ah it was Guess #2 sorry for the trouble, all working now, thank you for your help!

1 Like

Is it possible to turn on automations. For example to trigger an away mode ?

if there is an HA service you can call from ESPHome you could define a widget to trigger / turn it on…

Under the “on_json_message” you simply detect the assigned Widget ID and “on” message…

      - if:
          condition:
            lambda: 'return (type == 0x86 && root.containsKey("id") && strcasecmp(root["id"], "test_03") == 0);'
          then:
            - if:
                condition:
                  lambda: 'return (root["params"].containsKey("switch") && root["params"]["switch"] == "on");'
                then:
                  - homeassistant.service:
                      service: automation.trigger
                      data:
                        entity_id: automation_name

If you dont update the Panel to keep the widget “on” it will return to “off” by itself…and be able to trigger again

For my production use case I intend to use the simple toggle widget to send a number of WLED presets to some of my LED lights. because you have the full power of ESPHome you’re not tied to the actions being related to just switches/lights - e.g. could have multiple presses cycle through a number of presets / automations etc.

Thanks for your explanation. I will try it :+1:t2:

Hi,

I’m in the process of writing a new TFT which can be used over MQTT. The Nextion talks back to the ESP in much the same way as the stock screen does. I have this working with Tasmota already but it should be pretty easy to get it working with ESPhome too.

All it need is the wrapper for sending MQTT to and from the screen.

I don’t know much about the ESPHome side bit I know someone has done the ESPHome part for talkign to the orginal stock HMI screen. If that is there, it should be a trival change to get it to talk to my screen.

Can the persons or person(s) that did that help me out?

Would be good to have a HMI which could work out the box with both ESPHome and tasmota. I know people are working on version that talk directly, but I think an MQTT offering would be nice too.

Anyone can help?

1 Like

Mike - the current nspanel component that works with the default HMI was written by one of the ESPHome/HA developers Jesserockz . I’ve used the component to implement more functionality by interacting with the JSON messaging directly. The nspanel component is on github and my ESPHome yaml is on my github aswell.

ESPhome has an MQTT component so should be a case of he translation between MQTT receieved and send to Panel …and the receive serial from panel and translate to MQTT ?

Hi,

Would anyone like to take on the ESP changes to talk to this?

image

There is a lot of functionality behind this, buttons (configurable at runtime), thermostat, alarm, notifications, music player, dimmers, color wheels…

Using that same encoding used to talk to the stock HMI, which is;
(in berry script - but I’m sure easy to follow logic, and you must be doing this already to talk to stock)

    static header = bytes().fromstring("PS")

    def encode(payload)
      var b = bytes()
      b += self.header
      var nsp_type = 0 # not used
      b.add(nsp_type)       # add a single byte
      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

I dont use the nsp_type byte though, so you can forget about that, leave it zero. Also, output back from the HMI is straight text json, so you can handle that directly. But other than that, same basic mechanism as talking to stock.

To test you can talk to it, a simple test is to send;

{ "switches": { "switch1": 0 , "switch2": 0 } }

which will visual turn the GUI above the switch on/off.

Other example you can try are;

{ "weather": {  "temp": 27, "icon": "10d", "feels": 4 } }
{ "notifications": {  "text": "New notification" } }
{ "clock": { "date":22,"month":1,"year":2022,"weekday":6,"hour":17,"min":1} }
{ "summary": {  "temp": 17, "summ_text":  "New notification" } }
{ "warnings":[{"id":3,"type":"house","state":2},{"id":3,"type":"house","state":1}] }

Here is the current prototype HMI, if anyone want to help? :slight_smile:

Once you get the blocks in place to turn the switch visually on/off. you’ll have access to al the rest via mqtt too!!! :slight_smile:

Here is the berry script I use to talk to the HMI as a reference;
(this is how I get tasmota to talk to it. most of the script is for flashing the tas, the part dealing with the comms is pretty minimal. ESPHome will do it differently, but it’s here to show how minimal it would be, even done another way)

I’m sure anyone involved to doing the original interface to talk to stock will get this fully working in no time! :slight_smile:

NxPanel - New Enhanced Replacement for Stock Screen Firmware

No Nextion required - Totally control by JSON messages and/or MQTT

(ESPHome interface still required)

I’ve received a couple of EU NSPanels V1.8 and have successfully flashed NodeMCU PyFlasher, but when I wire the device up to mains it doesn’t appear to do anything and the screen doesn’t come on. I followed the instructions from Flashing the Sonoff NSPanel with ESPHome - how to get a custom UI for Home Assistant! - YouTube. Any ideas what I’ve done wrong?

If I take the link off from IO0 and reboot I can see in the console the following code scrolling over and over again:

[00:11:45]rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
[00:11:45]invalid header: 0x400d4b62
[00:11:45]invalid header: 0x400d4b62
[00:11:46]invalid header: 0x400d4b62
[00:11:46]invalid header: 0x400d4b62
[00:11:46]invalid header: 0x400d4b62
[00:11:46]invalid header: 0x400d4b62
[00:11:46]invalid header: 0x400d4b62
[00:11:46]ets Jul 29 2019 12:21:46

Any help gratefully appreciated :slight_smile:

If I use esphome-flasher it works :slight_smile:

1 Like

Love all this work in here have two screens trying the configs you all post, massive help they are. Yet I am so out of my depth with this, my question is as follows!

If I change a state of a button, an entity in HA, how do I update this as a button toggled in the NSPanel, do I need to send a JSON snippet to use that or is there a printf how do I sync an action triggered on HA or another physical button, with a switch being changed state on the NSPanel?

All help appreciated.

Are you using the stock HMI ? (and the ESPHome nspanel component) or a custom HMI and the ESPhome nextion component ? or Tasmota… ?