Integrate Easyplus Home Automation

Would it be possible to integrate EasyPlus into HA
http://www.apexsyst.com

Easy Plus features an open source platform for integrators. You can log in to the system using TCP / IP.
Through this way you can start sending and receiving commands.

For example, a command that can be sent is “Setrelay 10, 1” This ensures that relay 10 is actuated.

For example, a command that can receive is “Temperature 3, 22.5” This means that the temperature in the third zone is 22.5 degrees Celsius.

For more information about the bus commands- download the manual:

If you can let me know what specific existing integration to use if there is one already that would be great. Also if you can point me how use telnet in HA as Easyplus uses Telnet on port 2024 to communicate to the central server.

Can you let me know if this is feasible to have it integrated, anysupport would be great.

Thank you.

Hi elRadix,
Did you make some progress on this?

Thanks
Wim

I have created some scripts, pm for more info.
What kind of system do you use?

Hi, I have the EPC07101 Easyplus Exclusive.

I have the same model. You need to setup appdaemon, Python and use the command-line switch.

I use custom made appdaemon script and Python script to connect through the EasyPlus telnet server on port 2024 to read the data from the bus server and set the state accordingly in home assistant.

If you have some Linux knowledge that will help to set it up as this is manual process. First you need to have a running hass installation preferably through venv or Docker (not hass OS).

command line switch :

- platform: command_line
  switches:
   stp_keuken_microgolf:
        command_on: "python3 /opt/scripts/apex.py 'Setrelay 33,1'"
        command_off: "python3 /opt/scripts/apex.py 'Setrelay 33,0'" 
        friendly_name: microgolf

- platform: command_line
  switches:
   light_wc:
        command_on: "python3 /opt/scripts/apex.py 'SetAnalogOut 4,150'"
        command_off: "python3 /opt/scripts/apex.py 'SetAnalogOut 4,0'"
        friendly_name: WC

Python script to control the switches and lights:

import pexpect
import sys
import urllib.request
import time

class Apex():

    def __init__(self):
        self.i = 0
        self.connect = False
        self.password = 'Pass xxxx\r'
        self.child = pexpect.spawn('telnet 192.168.3.61 2024', timeout = 1)

    def apex_main(self):
        self.apex_test()
        if self.connect == False:
            self.easyplus_on
            while True:
                self.apex_test()
                if self.connect or self.i >= 20:
                  break
        self.apex_connect()
        self.apex_command()

    def apex_test(self):
        print("testing")
        try:
            self.child.expect(b'>Ready')
            print (self.child.before)
            self.connect = True
            print("try successfull")
        except:
            self.i += 1
            self.connect = False
            print("easyplus unavailable, connecting "+str(self.i))

    def apex_connect(self):
        print('connect')
        self.child.sendline('\r')
        self.child.sendline(self.password)

    def apex_command(self):
        print("command")
        self.child.sendline(str(sys.argv[1])+'\r')
        self.child.sendline('\r')
        self.child.close()
        print(self.child.exitstatus, self.child.signalstatus)
        exit(0)

object = Apex()
object.apex_main()

1 Like

Thanks a lot!
Day 1 with home assistant and looks like I picked the wrong way of installing HA. :slight_smile:

Thanks for the script!
I’ve also got a EPC07101 Easyplus Exclusive at home.

Can you explain me what you added to appdaemon? The post above only contains a python script and command line switches to activate them.
– edit –
after reading some more more about appdaemon it seems that the python script is in fact an appdaemon app.
You mention /opt/scripts/apex.py in your command_line switch for HA. Could you explain me what you did in that one to connect HA to the appdaemon app?
– end edit –

I would love to integrate my Easyplus setup with Home Assistant since the new things I’m adding will be Home Assistant integrated as well (energy monitoring from Shelly and maybe some LED light bulbs as well).

Thanks,
Bob

Nice to have more people interested in converting their Easyplus installation to Home Assistant.

So you already are able to control your switches using the switches/lights and heating using the script above. Which is just a python script which I call through the command line switch.

Next step is to gate the state of these entities synchronized with Home assistant, I am using AD to solve this.

I’m using a CSV file to load all the entities in to home assistant.

I have an the following AD scripts:

1- easyplus_live.py - get live updates

import appdaemon.plugins.hass.hassapi as hass
import telnetlib
import socket
import threading
import eebs
from eebs import DICT #contains csv switches telnet code and hass attributes
import re
import time
from datetime import datetime, date, time, timedelta
version = 'EEBS v0.1.1' # 2 attributes added device class and unit of measure

class EasyplusLive(hass.Hass):

    def initialize(self):

        self.log(version)
        self.depends_on_module(eebs) #import dict based on csv

# set parameters that are fixed
        self.HOST = self.args["host"] #set telnet ip
        self.PORT = self.args["port"] #set telnet port
        self.TIMEOUT = 10 #set telnet timeout
        self.PASS = self.args["pass"]
        self.GETDATA = "getdata\r\n"
        self.REGEX = r">(.+) (\d+),([0-9]*[.]{0,1}[0-9]*\w*),?(,*\d+)*"
        self.EEBS = telnetlib.Telnet() #telnet object
        self.log_level = 0 #set to 0 to supress logs in functions
        self.connect = False #means telnet conencted and ready to read data
        self.count = 0
        self.states = 0
        # start = self.datetime() + timedelta(seconds=1)
        
        self.loop_live = threading.Thread(target=self.EEBS_live)
        self.loop_live.start()

        self.loop_setstate = threading.Thread(target=self.EEBS_setstate)
        self.loop_setstate.start()

# easyplus component start getdata schedule and live scan
        self.listen_state(self.EEBS_live, 'binary_sensor.easyplus_telnet')
        self.set_state('binary_sensor.easyplus_telnet', state = "off")
        # self.run_every(self.EEBS_get, start, 60*5)

    # def EEBS_get(self, kwargs):
    #     if self.get_state('binary_sensor.easyplus_telnet') == "on":
    #         self.log("EEBS_getdata ...")
    #         self.EEBS.write(self.GETDATA.encode())

    def EEBS_live(self, entity, attribute, old, new, kwargs):
        if new == "on":
            self.log("EEBS_live initiated")
            self.EEBS.open(self.HOST,self.PORT,self.TIMEOUT)
            self.EEBS.write(self.PASS.encode())
            self.log("connection successful")
            self.log("EEBS_live is ready")
            self.set_state("sensor.notify_message", state="Easyplus Telnet is Live") 
            self.connect = True

        if new == "off":
    # def EEBS_stop(self, entity, attribute, old, new, kwargs):
            self.log("EEBS_stop - connection closed")
            self.connect = False
            #if self.log_level > 0:
            self.log("ID's Processed: %s", self.count, log="easyplus_stats")
            self.log("States Processed: %s", self.states, log="easyplus_stats")
            self.set_state("sensor.notify_message", state="Easyplus Telnet is down") 

        while self.connect:
            self.EEBS_read(kwargs)
            # if ">".encode() in self.data:
            self.EEBS_encode(kwargs)
            self.EEBS_setstate(kwargs)
            if self.get_state('binary_sensor.easyplus_telnet') == "off":
                self.connect = False
                break

    def EEBS_read(self, kwargs):
        if self.log_level > 0:
            self.log("EEBS_read started")
        self.data = self.EEBS.read_until(b"\r\n", timeout=1).strip()

    def EEBS_encode(self, kwargs):
        if self.log_level > 0:
            self.log("EEBS_encode - read until: " + str(self.data))
        self.string = self.data.decode()
        easyplus_data = re.search(self.REGEX, self.string)
        if self.log_level > 0:
            self.log(self.string)
        if easyplus_data is not None:
            self.easyplus_id = easyplus_data.group(1)+" "+easyplus_data.group(2)
            self.easyplus_state = easyplus_data.group(3)
        else:
            self.easyplus_id = ''
            self.easyplus_state = ''
        if self.log_level > 0:
            self.log(self.easyplus_id)
            self.log(self.easyplus_state)

    def EEBS_setstate(self, kwargs):
        if self.log_level > 0:
            self.log("EEBS_setstate - " + self.easyplus_id)
        for key in DICT.keys():
            if key == self.easyplus_id and DICT[key]["type"] in ['heating', 'light', 'motion', 'switch'] and self.easyplus_state.lower() != self.get_state(DICT[key]["entity"]): #additional condition to only set state if current and new different (works in jupyter but not in ad)
                self.set_state("{}".format(DICT[key]["entity"]), state = "{}".format(self.easyplus_state.lower()), attributes = {'friendly_name':"{}".format(DICT[key]["friendly_name"]),'icon': "{}".format(DICT[key]["icon"]),'device_class': "{}".format(DICT[key]["class"]),'unit_of_measurement': "{}".format(DICT[key]["unit"])})
                self.log(DICT[key]["friendly_name"] +' '+ self.easyplus_state.lower())
                self.states += 1
            elif key == self.easyplus_id and DICT[key]["type"] == 'dimmer':
                if int(self.easyplus_state) == 0 and self.get_state(DICT[key]["entity"]) != "off":
                    self.set_state("{}".format(DICT[key]["entity"]), state = 'off', attributes = {'friendly_name':"{}".format(DICT[key]["friendly_name"]),'icon': "{}".format(DICT[key]["icon"])})
                    self.log(DICT[key]["friendly_name"] +' off '+ self.easyplus_state.lower())
                    self.states += 1
                elif int(self.easyplus_state) != 0 and self.get_state(DICT[key]["entity"]) == "off":
                    self.set_state("{}".format(DICT[key]["entity"]), state = 'on', attributes = {'friendly_name':"{}".format(DICT[key]["friendly_name"]),'icon': "{}".format(DICT[key]["icon"])})
                    self.log(DICT[key]["friendly_name"] +' on '+ self.easyplus_state.lower())
                    self.states += 1
            elif key == self.easyplus_id and DICT[key]["type"] == 'led':
                if self.easyplus_state.lower() in ['long', 'both', 'short'] and self.get_state(DICT[key]["entity"]) != "on":
                    self.set_state("{}".format(DICT[key]["entity"]), state = 'on', attributes = {'friendly_name':"{}".format(DICT[key]["friendly_name"]),'icon': "{}".format(DICT[key]["icon"])})
                    self.log(DICT[key]["friendly_name"] +' on '+ self.easyplus_state.lower())
                    self.states += 1
                elif self.easyplus_state.lower() == "off" and self.get_state(DICT[key]["entity"]) != "off":
                    self.set_state("{}".format(DICT[key]["entity"]), state = 'off', attributes = {'friendly_name':"{}".format(DICT[key]["friendly_name"]),'icon': "{}".format(DICT[key]["icon"])})
                    self.log(DICT[key]["friendly_name"] +' off '+ self.easyplus_state.lower())
                    self.states += 1
        self.count += 1

2- easyplus_get.py - 15min synchronisation after reboot

import appdaemon.plugins.hass.hassapi as hass
import telnetlib
import eebs
from eebs import DICT
import re
import time
from datetime import datetime, date, time, timedelta
version = 'EEBS v0.1.1' # 2 attributes added device class and unit of measure

class EasyplusGet(hass.Hass):

    def initialize(self):

        self.log(version)
        self.depends_on_module(eebs)

# set parameters that are fixed
        self.HOST = self.args["host"] #set telnet ip
        self.PORT = self.args["port"] #set telnet port
        self.TIMEOUT = 10 #set telnet timeout
        self.PASS = self.args["pass"]
        self.GETDATA = "getdata\r\n"
        self.REGEX = r">(.+) (\d+),([0-9]*[.]{0,1}[0-9]*\w*),?(,*\d+)*"
        self.EEBS = telnetlib.Telnet() #telnet object
        self.log_level = 0 #set to 0 to supress logs in functions
        start = self.datetime() + timedelta(seconds=1)
        
        #self.loop_getdata = threading.Thread(target=self.EEBS_getdata)
        #self.loop_getdata.start()

        #self.loop_setstate = threading.Thread(target=self.EEBS_setstate)
        #self.loop_setstate.start()


# easyplus component start getdata schedule and live scan
        self.run_every(self.EEBS_getdata, start, 60*2)

    def EEBS_getdata(self, kwargs):
        if self.log_level > 0:
            self.log(DICT)
        self.timer = self.datetime() + timedelta(seconds=0.01)
        if self.get_state('binary_sensor.easyplus_telnet') == "on":
            self.log("EEBS_getdata connecting...")
            self.EEBS.open(self.HOST,self.PORT,self.TIMEOUT)
            self.EEBS.write(self.PASS.encode())
            self.EEBS.write("\r\n".encode())
            if self.log_level > 0:
                self.log("EEBS_getdata - connection successful")
                self.log("EEBS_getdata - request sent")
            self.EEBS.write(self.GETDATA.encode())
            self.string = ''
            timeout = self.datetime() + timedelta(seconds=3)
            self.count = 0
            self.states = 0
            while True:
                self.EEBS_read(kwargs)
                if ">".encode() in self.data:
                    self.EEBS_encode(kwargs)
                    self.EEBS_setstate(kwargs)
                if str(self.string) == '>SerialID 448506' or self.datetime() > timeout:
                    break
            self.log("EEBS_getdata - completed")
            # self.EEBS.close()
            self.EEBS_stop(kwargs)


    def EEBS_stop(self, kwargs):
        self.log("EEBS_stop - completed")
        self.stats= (self.datetime() - self.timer)
        self.log("ID's Processed: %s", self.count, log="easyplus_stats")
        self.log("States Processed: %s", self.states, log="easyplus_stats")
        self.log("Time Processed: %s", self.stats, log="easyplus_stats")
        self.EEBS.close()


    def EEBS_read(self, kwargs):
        if self.log_level > 0:
            self.log("EEBS_read started")
        self.data=self.EEBS.read_until(b"\r\n", timeout=1).strip()
        if self.log_level > 0:
            self.log("EEBS_read - read until: " + str(self.data))

    def EEBS_encode(self, kwargs):
        if self.log_level > 0:
            self.log("EEBS_encode - read until: " + str(self.data))
        self.string = self.data.decode()
        easyplus_data = re.search(self.REGEX, self.string)
        if self.log_level > 0:
            self.log(self.string)
        if easyplus_data is not None:
            self.easyplus_id = easyplus_data.group(1)+" "+easyplus_data.group(2)
            self.easyplus_state = easyplus_data.group(3)
        else:
            self.easyplus_id = ''
            self.easyplus_state = ''
        if self.log_level > 0:
            self.log(self.easyplus_id)
            self.log(self.easyplus_state)

    def EEBS_setstate(self, kwargs):
        if self.log_level > 0:
            self.log("EEBS_setstate - " + self.easyplus_id)
        for key in DICT.keys():
            if key == self.easyplus_id and DICT[key]["type"] in ['heating', 'light', 'motion', 'switch'] and self.easyplus_state.lower() != self.get_state(DICT[key]["entity"]): #additional condition to only set state if current and new different (works in jupyter but not in ad)
                self.set_state("{}".format(DICT[key]["entity"]), state = "{}".format(self.easyplus_state.lower()), attributes = {'friendly_name':"{}".format(DICT[key]["friendly_name"]),'icon': "{}".format(DICT[key]["icon"]),'device_class': "{}".format(DICT[key]["class"]),'unit_of_measurement': "{}".format(DICT[key]["unit"])})
                self.log(DICT[key]["friendly_name"] +' '+ self.easyplus_state.lower())
                self.states += 1
            elif key == self.easyplus_id and DICT[key]["type"] == 'dimmer':
                if int(self.easyplus_state) == 0 and self.get_state(DICT[key]["entity"]) != "off":
                    self.set_state("{}".format(DICT[key]["entity"]), state = 'off', attributes = {'friendly_name':"{}".format(DICT[key]["friendly_name"]),'icon': "{}".format(DICT[key]["icon"])})
                    self.log(DICT[key]["friendly_name"] +' off '+ self.easyplus_state.lower())
                    self.states += 1
                elif int(self.easyplus_state) != 0 and self.get_state(DICT[key]["entity"]) == "off":
                    self.set_state("{}".format(DICT[key]["entity"]), state = 'on', attributes = {'friendly_name':"{}".format(DICT[key]["friendly_name"]),'icon': "{}".format(DICT[key]["icon"])})
                    self.log(DICT[key]["friendly_name"] +' on '+ self.easyplus_state.lower())
                    self.states += 1
            elif key == self.easyplus_id and DICT[key]["type"] == 'led':
                if self.easyplus_state.lower() in ['long', 'both', 'short'] and self.get_state(DICT[key]["entity"]) != "on":
                    self.set_state("{}".format(DICT[key]["entity"]), state = 'on', attributes = {'friendly_name':"{}".format(DICT[key]["friendly_name"]),'icon': "{}".format(DICT[key]["icon"])})
                    self.log(DICT[key]["friendly_name"] +' on '+ self.easyplus_state.lower())
                    self.states += 1
                elif self.easyplus_state.lower() == "off" and self.get_state(DICT[key]["entity"]) != "off":
                    self.set_state("{}".format(DICT[key]["entity"]), state = 'off', attributes = {'friendly_name':"{}".format(DICT[key]["friendly_name"]),'icon': "{}".format(DICT[key]["icon"])})
                    self.log(DICT[key]["friendly_name"] +' off '+ self.easyplus_state.lower())
                    self.states += 1
        self.count += 1

3- eebs.py - global variables

# import appdaemon.plugins.hass.hassapi as hass
import csv
import appdaemon.plugins.hass.hassapi as hass
import threading
import telnetlib
import shelve
import re
import time
from datetime import datetime, date, time, timedelta

reader = csv.DictReader(open('/config/appdaemon/apps/easyplus.csv'))

DICT = {}
for row in reader:
    key = row.pop('id')
    DICT[key] = row

HOST = "192.168.x.x" #set telnet ip
PORT = "2024" #set telnet port
TIMEOUT = 10 #set telnet timeout
PASS = "pass xxxx\r\n"
GETDATA = "getdata\r\n"
REGEX = r">(.+\d+),(\d.+\d{0,2}?|OFF|ON|SHORT|LONG|BOTH|OTHER)"
EEBS = telnetlib.Telnet() #telnet object
LOGGING = 0 #set to 0 to supress logs in functions

4- easyplus.yaml - AD apps config

global_modules:
  - eebs

live:
  module: easyplus_live
  class: EasyplusLive
  priority: 2
  log: easyplus_live_log
  host: "192.168.xx.xx"
  port: "2024"
  pass: "pass xxxx\r\n"

getdata:
  module: easyplus_get
  class: EasyplusGet
  priority: 1
  log: easyplus_get_log
  host: "192.168.xx.xx"
  port: "2024"
  pass: "pass xxx\r\n"

5- easyplus.csv - list entities with attributes

id,service_on,service_off,service_state,entity,light,friendly_name,icon,type,room,class,unit
AnalogOut 0,"SetAnalogOut 0, 255","SetAnalogOut 0, 0",,switch.light_keuken_spot_links,light_keuken_spot_links,Keueken Spot links,mdi:spotlight-beam,dimmer,keuken,,
AnalogOut 1,"SetAnalogOut 1, 255","SetAnalogOut 1, 0",,switch.light_keuken_spot_rechts,light_keuken_spot_rechts,Keuken Spot rechts,mdi:spotlight-beam,dimmer,keuken,,
AnalogOut 10,"SetAnalogOut 10, 255","SetAnalogOut 10, 0",,switch.light_living_center,light_living_center,Center,mdi:spotlight-beam,dimmer,living,,
AnalogOut 12,"SetAnalogOut 12, 255","SetAnalogOut 12, 0",,switch.light_living_triple_spot,light_living_triple_spot,Triple spot,mdi:spotlight-beam,dimmer,living,,
AnalogOut 13,"SetAnalogOut 13, 255","SetAnalogOut 13, 0",,switch.light_bureau_spots,light_bureau_spots,Bureau Spots,mdi:spotlight-beam,dimmer,bureau,,
AnalogOut 14,"SetAnalogOut 14, 255","SetAnalogOut 14, 0",,switch.light_trap_voor,light_trap_voor,Slaapkamer,mdi:spotlight-beam,dimmer,traphal,,
AnalogOut 15,"SetAnalogOut 15, 255","SetAnalogOut 15, 0",,switch.light_trap_achter,light_trap_achter,Badkamer,mdi:spotlight-beam,dimmer,traphal,,
AnalogOut 16,"SetAnalogOut 16, 255","SetAnalogOut 16, 0",,switch.light_slp1_double,light_slp1_double,Double,mdi:spotlight-beam,dimmer,slaapkamer,,
AnalogOut 17,"SetAnalogOut 17, 255","SetAnalogOut 17, 0",,switch.light_slp1_deur,light_slp1_deur,Deur,mdi:spotlight-beam,dimmer,slaapkamer,,
AnalogOut 17,"SetAnalogOut 17, 150","SetAnalogOut 17, 0",,switch.light_slp1_deur_morning,light_slp1_deur_morning,Deur,mdi:spotlight-beam,dimmer,slaapkamer,,
AnalogOut 18,"SetAnalogOut 18, 255","SetAnalogOut 18, 0",,switch.light_slp1_soumaya,light_slp1_soumaya,Light Soumaya,mdi:spotlight-beam,dimmer,slaapkamer,,
AnalogOut 19,"SetAnalogOut 19, 255","SetAnalogOut 19, 0",,switch.light_slp1_rachid,light_slp1_rachid,Light Rachid,mdi:spotlight-beam,dimmer,slaapkamer,,
AnalogOut 2,"SetAnalogOut 2, 255","SetAnalogOut 2, 0",,switch.light_eetkamer_double_spot,light_eetkamer_double_spot,Double spot,mdi:spotlight-beam,dimmer,eetkamer,,
AnalogOut 20,"SetAnalogOut 20, 255","SetAnalogOut 20, 0",,switch.light_slp2_deur,light_slp2_deur,Deur,mdi:spotlight-beam,dimmer,slaapkamer,,
AnalogOut 21,"SetAnalogOut 21, 255","SetAnalogOut 21, 0",,switch.light_slp2_kast,light_slp2_kast,Kast,mdi:spotlight-beam,dimmer,slaapkamer,,
AnalogOut 22,"SetAnalogOut 22, 255","SetAnalogOut 22, 0",,switch.light_slp3_deur,light_slp3_deur,Deur,mdi:spotlight-beam,dimmer,slaapkamer,,
AnalogOut 23,"SetAnalogOut 23, 255","SetAnalogOut 23, 0",,switch.light_badkamer_wc,light_badkamer_wc,Spot WC,mdi:spotlight-beam,dimmer,eetkamer,,
AnalogOut 3,"SetAnalogOut 3, 255","SetAnalogOut 3, 0",,switch.light_eetkamer_center,light_eetkamer_center,Center spot,mdi:spotlight-beam,dimmer,eetkamer,,
AnalogOut 4,"SetAnalogOut 4, 255","SetAnalogOut 4, 0",,switch.light_wc,light_wc,WC,mdi:lightbulb,dimmer,wc,,
AnalogOut 5,"SetAnalogOut 5, 255","SetAnalogOut 5, 0",,switch.light_inkom,light_inkom,Inkom,mdi:spotlight-beam,dimmer,inkomhal,,
AnalogOut 7,"SetAnalogOut 7, 255","SetAnalogOut 7, 0",,switch.light_keuken_spot_front,light_keuken_spot_front,Keuken Spot wasbak,mdi:spotlight-beam,dimmer,keuken,,
AnalogOut 8,"SetAnalogOut 8, 255","SetAnalogOut 8, 0",,switch.light_living_double_spot,light_living_double_spot,Double spot,mdi:spotlight-beam,dimmer,living,,
DigitalIn 0,,,,binary_sensor.motion_wc,,WC motion ,mdi:motion-sensor,motion,wc,motion,
DigitalIn 1,,,,binary_sensor.motion_eetkamer,,Eetkamer motion,mdi:motion-sensor,motion,eetkamer,motion,
DigitalIn 2,,,,binary_sensor.motion_inkomhal,,Inkomhal motion,mdi:motion-sensor,motion,inkomhal,motion,
DigitalIn 3,,,,binary_sensor.motion_traphal,,traphal motion ,mdi:motion-sensor,motion,traphal,motion,
DigitalIn 4,,,,binary_sensor.motion_badkamer,,badkamer motion,mdi:motion-sensor,motion,badkamer,motion,
DigitalOut 0,"Setrelay 0,1","Setrelay 0,0",Getrelay 0,switch.light_berging_center,light_berging_center,Lamp,mdi:lightbulb-cfl-spiral,switch,berging,,
DigitalOut 1,"Setrelay 1,1","Setrelay 1,0",Getrelay 1,switch.stp_keuken_dampkap,,dampkap,mdi:air-filter,switch,keuken,,
DigitalOut 10,"Setrelay 10,1","Setrelay 10,0",Getrelay 10,switch.light_trap_3,light_trap_3,Trap 3,mdi:lightbulb,switch,traphal,,
DigitalOut 11,"Setrelay 11,1","Setrelay 11,0",Getrelay 11,switch.light_trap_2,light_trap_2,Trap 2,mdi:lightbulb,switch,traphal,,
DigitalOut 12,"Setrelay 12,1","Setrelay 12,0",Getrelay 12,switch.light_trap_1,light_trap_1,Trap 1,mdi:lightbulb,switch,traphal,,
DigitalOut 13,"Setrelay 13,1","Setrelay 13,0",Getrelay 13,switch.light_slp1_center,light_slp1_center,Center,mdi:spotlight-beam,switch,slaapkamer,,
DigitalOut 18,"Setrelay 18,1","Setrelay 18,0",Getrelay 18,switch.stp_eetkamer_other,,Other,mdi:power-socket,switch,eetkamer,,
DigitalOut 19,"Setrelay 19,1","Setrelay 19,0",Getrelay 19,switch.stp_eetkamer_tv,,samsung,mdi:television-guide,switch,eetkamer,,
DigitalOut 2,"Setrelay 2,1","Setrelay 2,0",Getrelay 2,switch.light_vestiare,light_vestiare,Vestiaire,mdi:spotlight-beam,switch,inkomhal,,
DigitalOut 20,"Setrelay 20,1","Setrelay 20,0",Getrelay 20,switch.stp_living_bureau,,Bureau,mdi:power-socket-eu,switch,living,,
DigitalOut 21,"Setrelay 21,1","Setrelay 21,0",Getrelay 21,switch.stp_living_sony,,Sony TV,mdi:television,switch,living,,
DigitalOut 22,"Setrelay 22,1","Setrelay 22,0",Getrelay 22,switch.stp_living_other,,Other,mdi:power-socket-eu,switch,living,,
DigitalOut 24,"Setrelay 24,1","Setrelay 24,0",Getrelay 24,switch.stp_slp2_deur,,Deur,mdi:power-socket-eu,switch,slaapkamer,,
DigitalOut 25,"Setrelay 25,1","Setrelay 25,0",Getrelay 25,switch.stp_slp2_bureau,,Bureau,mdi:power-socket-eu,switch,slaapkamer,,
DigitalOut 26,"Setrelay 26,1","Setrelay 26,0",Getrelay 26,switch.stp_slp3_deur,,Deur,mdi:power-socket-eu,switch,slaapkamer,,
DigitalOut 27,"Setrelay 27,1","Setrelay 27,0",Getrelay 27,switch.stp_slp3_bureau,,Bureau,mdi:power-socket-eu,switch,slaapkamer,,
DigitalOut 28,"Setrelay 28,1","Setrelay 28,0",Getrelay 28,switch.stp_slp1_bed_soumaya,,Bed Soumaya,mdi:power-sleep,switch,slaapkamer,,
DigitalOut 29,"Setrelay 29,1","Setrelay 29,0",Getrelay 29,switch.stp_slp1_bed,,Bed Rachid,mdi:power-sleep,switch,slaapkamer,,
DigitalOut 33,"Setrelay 33,1","Setrelay 33,0",Getrelay 33,switch.stp_keuken_microgolf,,microgolf,mdi:microwave,switch,keuken,,
DigitalOut 34,"Setrelay 34,1","Setrelay 34,0",Getrelay 34,switch.stp_keuken_oven,,oven,mdi:stove,switch,keuken,,
DigitalOut 35,"Setrelay 35,1","Setrelay 35,0",Getrelay 35,switch.stp_keuken_espresso,,espresso,mdi:coffee-maker,switch,keuken,,
DigitalOut 36,"Setrelay 36,1","Setrelay 36,0",Getrelay 36,switch.stp_berging_was,,was,mdi:washing-machine,switch,berging,,
DigitalOut 37,"Setrelay 37,1","Setrelay 37,0",Getrelay 37,switch.stp_berging_dryer,,dryer,mdi:tumble-dryer,switch,berging,,
DigitalOut 38,"Setrelay 38,1","Setrelay 38,0",Getrelay 38,switch.stp_keuken_dish,,dish,mdi:dishwasher,switch,keuken,,
DigitalOut 39,"Setrelay 39,1","Setrelay 39,0",Getrelay 39,switch.stp_keuken_waterkoker,,waterkoker,mdi:water-pump,switch,keuken,,
DigitalOut 4,"Setrelay 4,1","Setrelay 4,0",Getrelay 4,switch.light_slp3_kast,light_slp3_kast,Kast,mdi:spotlight-beam,switch,slaapkamer,,
DigitalOut 40,"Setrelay 40,1","Setrelay 40,0",Getrelay 40,switch.stp_keuken_commander,,commander,mdi:delete-empty,switch,keuken,,
DigitalOut 5,"Setrelay 5,1","Setrelay 5,0",Getrelay 5,switch.light_slp3_muur,light_slp3_muur,Muur,mdi:spotlight-beam,switch,slaapkamer,,
DigitalOut 32,"Setrelay 32,1","Setrelay 32,0",Getrelay 32,switch.light_badkamer_spiegel,light_badkamer_spiegel,Spiegel,mdi:spotlight-beam,switch,badkamer,,
DigitalOut 6,"Setrelay 6,1","Setrelay 6,0",Getrelay 6,switch.light_badkamer_douche,light_badkamer_douche,Douche,mdi:spotlight-beam,switch,badkamer,,
DigitalOut 64,"Setrelay 64,1","Setrelay 64,0",Getrelay 64,switch.heating_eetkamer,,Eetkamer heating ,mdi:radiator,heating,eetkamer,,
DigitalOut 65,"Setrelay 65,1","Setrelay 65,0",Getrelay 65,switch.heating_living,,Living heating ,mdi:radiator,heating,living,,
DigitalOut 66,"Setrelay 66,1","Setrelay 66,0",Getrelay 66,switch.heating_badkamer,,Badkamer heating ,mdi:radiator,heating,badkamer,,
DigitalOut 67,"Setrelay 67,1","Setrelay 67,0",Getrelay 67,switch.heating_floradix,,S&R heating ,mdi:radiator,heating,slaapkamer,,
DigitalOut 68,"Setrelay 68,1","Setrelay 68,0",Getrelay 68,switch.heating_sara,,Sara heating ,mdi:radiator,heating,slaapkamer,,
DigitalOut 69,"Setrelay 69,1","Setrelay 69,0",Getrelay 69,switch.heating_yassin,,Yassin heating ,mdi:power-socket-eu,heating,slaapkamer,,
DigitalOut 7,"Setrelay 7,1","Setrelay 7,0",Getrelay 7,switch.light_badkamer_lavabo,light_badkamer_lavabo,Lavabo,mdi:spotlight-beam,switch,badkamer,,
DigitalOut 76,"Setrelay 76,1","Setrelay 76,0",Getrelay 76,switch.light_bureau_tl,light_bureau_tl,Bureau TL,mdi:lightbulb,switch,bureau,,
DigitalOut 8,"Setrelay 8,1","Setrelay 8,0",Getrelay 8,switch.light_trap_5,light_trap_5,Trap 5,mdi:lightbulb,switch,traphal,,
DigitalOut 9,"Setrelay 9,1","Setrelay 9,0",Getrelay 9,switch.light_trap_4,light_trap_4,Trap 4,mdi:lightbulb,switch,traphal,,
Led 60,"Setled60,3","Setled60,0",Getled 60,binary_sensor.keuken_microgolf,,microgolf,mdi:microwave,led,keuken,,
Led 61,"Setled61,3","Setled61,0",Getled 61,binary_sensor.keuken_oven,,oven,mdi:stove,led,keuken,,
Led 62,"Setled62,3","Setled62,0",Getled 62,binary_sensor.keuken_waterkoker,,waterkoker,mdi:water-pump,led,keuken,,
Led 63,"Setled63,3","Setled63,0",Getled 63,binary_sensor.keuken_dish,,dish,mdi:dishwasher,led,keuken,,
Temperature 0,,,Gettempinfo 0,sensor.tmp_living_source,,Living temperature,mdi:temperature-celsius,heating,living ,temperature,°C
Temperature 7,,,Gettempinfo 7,sensor.tmp_slp_1_source,,Slp 1 temperature,mdi:temperature-celsius,heating,floradix,temperature,°C
Temperature 5,,,Gettempinfo 5,sensor.tmp_slp_2_source,,Slp 2 temperature,mdi:temperature-celsius,heating,sara,temperature,°C
Temperature 6,,,Gettempinfo 6,sensor.tmp_slp_3_source,,Slp 3 temperature,mdi:temperature-celsius,heating,yassin,temperature,°C
Temperature 10,,,Gettempinfo 10,sensor.tmp_badkamer_source,,Badkamer temp,mdi:temperature-celsius,heating,badkamer,temperature,°C
TempSetpoint 0,"Setsetpoint 0, ",,,sensor.tmp_set_living,,Living setpoint,mdi:temperature-celsius,heating,living,temperature,°C
TempSetpoint 7,"Setsetpoint 7, ",,,sensor.tmp_set_slp_1,,Slp 1 setpoint,mdi:temperature-celsius,heating,floradix,temperature,°C
TempSetpoint 5,"Setsetpoint 5,",,,sensor.tmp_set_slp_2,,Slp 2 setpoint,mdi:temperature-celsius,heating,sara,temperature,°C
TempSetpoint 6,"Setsetpoint 6, ",,,sensor.tmp_set_slp_3,,Slp 3 setpoint,mdi:temperature-celsius,heating,yassin,temperature,°C
TempSetpoint 10,"Setsetpoint 10,",,,sensor.tmp_set_badkamer,,Badkamer setpoint,mdi:temperature-celsius,heating,badkamer,temperature,°C
TempControl 0,,,,binary_sensor.heat_living,,Living heat control,mdi:radiator,heating,living,heat,
TempControl 7,,,,binary_sensor.heat_slp_1,,Slp 1 heat control,mdi:radiator,heating,floradix,heat,
TempControl 5,,,,binary_sensor.heat_slp_2,,Slp 2 heat control,mdi:radiator,heating,sara,heat,
TempControl 6,,,,binary_sensor.heat_slp_3,,Slp 3 heat control,mdi:radiator,heating,yassin,heat,
TempControl 10,,,,binary_sensor.heat_badkamer,,Badkamer heat control,mdi:radiator,heating,badkamer,heat,

If you encounter issues or have more questions let me know.

1 Like

Thanks a lot!
I’ll give try that in the coming days and let you know :smile:

I’m trying to get the first script (set relay / dimmer) working on a linux box. The image in attachment is the output I get. All seems fine but the light doesn’t turn on.

Any idea what happens? I’ve added debugging to see the command sent to the bus server and that seems to be correct.

It is best run also another telnet session by connecting directly tot port 2024 with your easyplus ip in order to make sure your using the correct ID of your relay. You then push the button on the wall button and see actions on your telnet session running live.

And replicate the command with the correct ID.

It turned out to be a wrong password.
In the easyplus configuration utility it works because it gets truncated somehow when passing it on to the controller …

I’ll continue my tests with the correct password …

I don’t get the command_line switch working…

I’ve put the python script on /opt/scripts on my ubuntu host.
When I execute the script in the shell, it works fine.
Unfortunately I get this error when clicking the button in HA:

2021-01-06 20:41:53 ERROR (SyncWorker_2) [homeassistant.components.command_line.switch] Command failed: python3 /opt/scripts/apex.py 'SetAnalogOut 3,150'

My configuration.yaml file contains this for the button:

- platform: command_line
  switches:
   salon_hoek:
        command_on: "python3 /opt/scripts/apex.py 'SetAnalogOut 3,150'"
        command_off: "python3 /opt/scripts/apex.py 'SetAnalogOut 3,0'"
        friendly_name: Salonhoek

Any idea what I’m doing wrong?

Can you tell me how you installed home assistant… venv, docker or OS

I am using Home Assistant OS.
I forgot to tell you that you need some packages to be installed in order to get it running.

- platform: command_line
  switches:
   stp_keuken_espresso:
        command_on: "python3 /config/python_scripts/apex.py 'Setrelay 35,1'"
        command_off: "python3 /config/python_scripts/apex.py 'Setrelay 35,0'" 
        friendly_name: espresso

you can use a shell command for that as well

btw packages can be installed using the apk commands

I created a small bash script which a have included as a shell command and this runs whenever home assistant starts

file: setup. sh
#!/bin/sh
echo "Updating Image with Tools"
apk update
apk add -u busybox
apk add busybox-extras
apk add expect
apk add sshpass
pip3 install pexpect
echo " Tools Installed"
- id: hass_tools
  initial_state: true
  alias: System Startup install tools
  trigger:
    platform: homeassistant
    event: start
  action:
  - service: shell_command.setup
shell_command_setup: "/config/scripts/setup.sh"

I did try Home Assistant OS first but switched to Ubuntu with Home Assistant installed using the guide below
https://www.jamestucker.me/post/install-home-assistant-on-ubuntu-server-20-04/
It is a docker based install using the Home Assistant supervised install script

Since my Home Assistant OS based install still exists, I will try there to be as close as possible to your setup.
I really appreciate your support to get this working :slight_smile:
Thanks!

on Home Assistant OS the script works at the command line as well.
triggered from Home Assistant command_line switch, it fails with the below message in the log

2021-01-06 23:04:05 INFO (MainThread) [homeassistant.components.switch] Setting up switch.command_line
2021-01-06 23:04:12 INFO (SyncWorker_0) [homeassistant.components.command_line.switch] Running command: python3 /config/python_scripts/apex.py 'SetAnalogOut 3,150'
2021-01-06 23:04:12 ERROR (SyncWorker_0) [homeassistant.components.command_line] Command failed: python3 /config/python_scripts/apex.py 'SetAnalogOut 3,150'
2021-01-06 23:04:12 ERROR (SyncWorker_0) [homeassistant.components.command_line.switch] Command failed: python3 /config/python_scripts/apex.py 'SetAnalogOut 3,150'

I’m going to call it a day and hope I can fix this tomorrow.

that’s strange.
can you add the following to the script setup. sh : apk add python3

I’m still struggling with the connection between HA and Easyplus.
As soon as I started using the command interface towards Easyplus my Easyplus IOS app lost its connection with the system.
From within HA (the OS version of it) the scripts don’t work. Even when adding the python3 line in setup.sh.

I’m working on 2 other things as well:

  • localtuya / tuyagateway (I prefer the 2nd option because it uses MQTT)
  • fetching the production of my solar panels (sunny boy RF connected via USB to a linux box) and adding it to InfluxDB / Grafana (plugins in HA)

Since I’m stuck with the Easyplus interaction, I’m going to focus on the 2 above now and come back to the Easyplus interface later on.
Thanks for the support and I’ll inform you soon about the status …

1 Like

Sure happy to help once you have more focus, maybe it’s just a configuration issue hopefully.

I don’t use the EasyPlus app, never liked that interface and lack of support from the supplier. I own mainly android devices.

Everything is done through the home assistant app here.

Hi,

I did manage to control the lights using a python script from within Home Assistant.
The startup script did it I think!

I’ve also configured the AppDaemon using the scripts you’ve posted above.
When I toggle a light (relay in Easyplus) using a physical button in our home, the state on the Home Assistant dashboard doesn’t change. How did you get the entities of AppDaemon in Home Assistant?

I noticed that the live app in AppDaemon (used in state callback) never gets triggered. Maybe I did something wrong there. The get app is being executed time driven.

Thanks,
Bob