ELV Max! Heating control system

For heating/cooling related questions in Domoticz

Moderator: leecollings

Teatech
Posts: 22
Joined: Sunday 22 November 2015 11:10
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.5877
Location: Finland
Contact:

Re: ELV Max! Heating control system

Post by Teatech »

I'm very interested to know how RF communication is made. They have achieved quite long battery time for valves. I'll try get my old 868MHz tranceiver to work. Maybe I can use it as sniffer and find out that communication.
User avatar
blackdog65
Posts: 311
Joined: Tuesday 17 June 2014 18:25
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Norfolk, UK
Contact:

Re: ELV Max! Heating control system

Post by blackdog65 »

Just installed the latest script in full and removed all the old stuff.
Happy to report everything working fine.
I'm thinking about incorporating some door sensors now if they are working ok.

Many thanks to everyone for all the work

Sean
CubieTruck Master
RasPi slaves
Aeon Labs Z-Stick, multi sensor
Fibaro Dimmers, relays, Universal sensors
EQ3 MAX!
TKB Sockets
RFXCOM
LightwaveRF sockets, switches, relays, doorbell
MySensors
ESPEasy ESP8266-12E
mvzut
Posts: 443
Joined: Thursday 12 November 2015 10:55
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: The Netherlands
Contact:

ELV Max! Heating control system

Post by mvzut »

The new script still functions nicely for me, but there is one serious issue/annoyence: I get way too many timeout warnings in my log. I know that they are just warnings, and that the script will still be executed. But I don't like the warnings, especially if there are a lot of them, they mess up the Error tab of my log screen and make it more difficult to spot occasional real errors.

That's when an alternative solution crossed my mind: why not run the lua ascript outside of Domoticz? I only needed a few modification for this to work, basically changing the ['openURL'] commands with http.request commands. I then added

Code: Select all

*/5 * * * * /usr/bin/lua /home/pi/domoticz/scripts/lua/script_time_max.lua
to my cronjobs with with crontab -e, and voila, it worked!

Now the devices are updated (and created if necessary) every 5 minutes without any required action from within Domoticz. That also means: no error messages.

If you also want to try this, and my instructions are too sparse for you, let me know, so that I can explain in more detail.
Raspberry Pi 4 - RFXtrx433 - CC2531 Zigbee - Opentherm Gateway - P1 smart meter - Netatmo - Philips Hue - ELV Max! - ESP8266 DIY water meter - 6 x Sonos - 4 x IP cameras - Wall mounted tablet + Dashticz - Google Home integration - MANY switches/sensors
User avatar
blackdog65
Posts: 311
Joined: Tuesday 17 June 2014 18:25
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Norfolk, UK
Contact:

Re: ELV Max! Heating control system

Post by blackdog65 »

mvzut wrote:If you also want to try this, and my instructions are too sparse for you, let me know, so that I can explain in more detail.
I'm in the same situation. Everything runs like a "Swiss Watch" except for these time out errors, so I'd really like to see what you've done :D

Sean
CubieTruck Master
RasPi slaves
Aeon Labs Z-Stick, multi sensor
Fibaro Dimmers, relays, Universal sensors
EQ3 MAX!
TKB Sockets
RFXCOM
LightwaveRF sockets, switches, relays, doorbell
MySensors
ESPEasy ESP8266-12E
YOYO
Posts: 27
Joined: Tuesday 09 June 2015 21:22
Target OS: Raspberry Pi / ODroid
Domoticz version: V2.23393
Location: The Netherlands
Contact:

Re: ELV Max! Heating control system

Post by YOYO »

Hello all,

It seems i have almost the script running although sending a setpoin by domoticz isnt working.
Furthermore there is an error occuring when im running the script but that seems to be time related i guess:

Code: Select all

2016-11-16 22:20:00.846 Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_time_max.lua: /home/pi/domoticz/scripts/lua/script_time_max.lua:21: bad argument #1 to 'sub' (string expected, got nil)
The script i have is not the last one mentioned in this thread but its the code thats actually on the WIKI page now.
I dont have a WMT (I have a RFX thermometer) so im bound to the valve reading and the setpoint from domoticz.

Who can help me out??

Code: Select all

--./script_time_max.lua
----------------------------------------------------------------------------------------------------------
-- Script parameters
----------------------------------------------------------------------------------------------------------
package.loadlib("core.so", "*")
local Socket = require "socket"
local Basexx = require "basexx"
 
local MaxIP='192.168.1.XXX'
local MaxPort = 62910
local useWMT = false --Set to true if there is a wall mounted thermostat in every room
local interval = 5 --Polling interval in minutes, possible range 1-59. Cube doesn't seem to like too frequent communication, 5 minutes is a safe value
local DomoticzPort = 8080
 
local Rooms   = {}
local Devices = {}
local Room_nums = {}
 
function age(timestring)
  t = {}
  t.year = string.sub(timestring,1,4)
  t.month = string.sub(timestring,6,7)
  t.day = string.sub(timestring,9,10)
  t.hour = string.sub(timestring,12,13)
  t.min = string.sub(timestring,15,16)
  t.sec = string.sub(timestring,18,19)
  return os.difftime(os.time(),os.time(t))
end
 
function maxCmd_H(data)
--   print('H='..data)
end
 
function maxCmd_M(data)
   i = 0
   j = 0
 
    while true do    -- find next comma
      i = string.find(data, ",", i+1)
      if not i then break end
     j = i
    end
 
   s   = data:sub(j+1)
   dec = Basexx.from_base64(s)
   num_rooms = string.byte(dec,3)
   pos=4
 
   for i=1, num_rooms do
      room_num = string.byte(dec, pos)
      name_len = string.byte(dec, pos+1)
      pos  = pos+2
      name = dec:sub(pos, pos+name_len-1)
      pos  = pos+name_len
      adr  = Basexx.to_hex(dec:sub(pos, pos+2))
      Rooms[room_num] = name
      pos = pos+3
   end
 
   num_devs = string.byte(dec, pos)
   for i=1, num_devs do
      dtype = string.byte(dec, pos+1)
      adr   = Basexx.to_hex(dec:sub(pos+2, pos+4))
      snum  = dec:sub(pos+5, pos+14)
      name_len = string.byte(dec, pos+15)
      pos  = pos+16
      name = dec:sub(pos, pos+name_len-1)
      pos  = pos+name_len
      room_num = string.byte(dec, pos)
      Room_nums[adr] = room_num
      Devices[adr] = name
   end
 
end
 
function maxCmd_C(data)
--   print('C='..data)
end
 
function maxCmd_L(data)
   pos = 1
   dec = Basexx.from_base64(data)
   L_hex = Basexx.to_hex(dec)
   L_len = string.len(L_hex)
 
   while (pos < L_len) do
 
      s = L_hex:sub(pos,(pos+1))
      data_len  = tonumber(s,16) + 1
      hex  = L_hex:sub(pos,pos+(data_len*2))
      adr  = hex:sub(3,8)
      room_num = string.format("%02X", Room_nums[adr])
      room = Rooms[Room_nums[adr]]
      name = Devices[adr]
      if not name then name=adr end
      valve_info = tonumber(hex:sub(13,14),16)
      batt = bit32.extract(valve_info,7,1)
      bst  = bit32.extract(valve_info,3,1)
      mode = bit32.extract(valve_info,0,2)
 
      if (batt==0) then sbat="OK" else sbat="Low" end
      if (mode==0) then smode="Auto" elseif (mode==1) then smode="Manual"
      elseif (mode==2) then smode="Holiday" elseif (mode==3) then smode="Boost" end
 
      if (data_len == 13) then   -- WallMountedThermostat (dev_type 3)
        valve_pos = -1
        s = hex:sub(17,18)
        setpoint = tonumber(s,16) / 2
        s = hex:sub(23,26)
        temp = tonumber(s,16) / 10
        dtype = "Thermostat"
      elseif (data_len == 12) then -- HeatingThermostat (dev_type 1 or 2)
        s = hex:sub(15,16)
        valve_pos = tonumber(s,16)
        s = hex:sub(17,18)
        setpoint = tonumber(s,16) / 2
        if (mode ~= 2) then
          s = hex:sub(19,22)
          temp = tonumber(s,16) / 10
        else
          temp = 0
        end
        dtype = "Valve"
      end
 
      --Following two lines correct temperatures over 25.5 degrees, since e.g. 26 degrees is reported as 0.5 degrees
      --This is due to the fact that temperatures seem to be stored as two Hex characters only (= max 255 in decimal)
      --Pending better solution
      if temp < 5 then temp = temp + 25.5 end
      if setpoint > 50 then setpoint = setpoint - 64 end
 
      -- Update virtual devices in Domoticz and update MAX! setpoints if necessary
 
      --print(dtype.."  "..name.."  Setpoint="..setpoint.."  Temp="..temp.."  Valve pos="..valve_pos)
      if dtype == "Valve" and name:sub(-5,-1) ~= "-Sens" then
        table.insert(commandArray, { ['UpdateDevice'] = otherdevices_idx[name]..'|0|'..valve_pos})   
        if not useWMT then --Use valve to update temperature and synchronize setpoints
          name = name:sub(1,-5) .. "-Stat"  -- set thermostat name to valve name with "-Stat" instead of "-Rad" suffix
          setpoint_Domoticz = tonumber(otherdevices_svalues[name])
          if setpoint_Domoticz ~= setpoint then
            if age(otherdevices_lastupdate[name]) > interval * 60 then --Domoticz thermostat value must be updated
              table.insert(commandArray, { ['OpenURL'] = 'http://127.0.0.1:'..DomoticzPort..'/json.htm?type=command&param=udevice&idx='..otherdevices_idx[name]..'&nvalue=0&svalue='..setpoint})
              print('Domoticz setpoint ' .. name .. ' updated')
            else --Max! setpoint must be updated
              MaxCmdSend(adr, room_num, "manual", setpoint_Domoticz)
              print('MAX! setpoint ' .. name .. ' updated')
            end
          end
        end
      elseif dtype == "Thermostat" then
        table.insert(commandArray, { ['UpdateDevice'] = otherdevices_idx[room]..'|0|'..temp})
        setpoint_Domoticz = tonumber(otherdevices_svalues[name])
        if setpoint_Domoticz ~= setpoint then
          if age(otherdevices_lastupdate[name]) > interval * 60 then --Domoticz thermostat value must be updated
            table.insert(commandArray, { ['OpenURL'] = 'http://127.0.0.1:'..DomoticzPort..'/json.htm?type=command&param=udevice&idx='..otherdevices_idx[name]..'&nvalue=0&svalue='..setpoint})
            print('Domoticz setpoint ' .. name .. ' updated')
          else --Max! setpoint must be updated
            MaxCmdSend(adr, room_num, "manual", setpoint_Domoticz)
            print('MAX! setpoint ' .. name .. ' updated')
          end
        end   
      end
 
      pos = pos + (data_len*2)
   end
end
 
 
function MaxCmdSend(id, room, mode, setpoint)
 
   bits  = setpoint * 2
   smode = string.upper(mode)
   if smode == 'MANUAL' then
      bits = 64 + bits
   elseif smode == 'BOOST' then
      bits = 192 + bits
   elseif smode == 'VACATION' then
      bits = 128 + bits
   end
 
   hex = "000440000000"..id..room..string.format("%x",bits)
   sendStr = Basexx.to_base64(Basexx.from_hex(hex))
   i, status = tcp:send("s:"..sendStr.."\r\n")
 
   if not i then
      print("MAX TCP send failed - "..status)
      return
   end
end
 
 
commandArray = {}
 
local m = os.date('%M')
if (m % interval == 0) and (m ~= 0) then
 
  tcp = Socket.connect(MaxIP, MaxPort)
  if not tcp then
    print("Socket connect failed for "..MaxIP..':'..MaxPort)
    return
  end
  tcp:settimeout(2)
 
  while true do
    s, status, partial = tcp:receive()
    if (status) then
      print("TCP receive - "..status)
     break
    end
 
    local line = (s or partial)
    local cmd  = line:sub(1,1)
    local data = line:sub(3)
 
    if (cmd == 'H') then
      status = maxCmd_H(data)
      if status == 'Error' then break end
    elseif (cmd == 'M') then
      maxCmd_M(data)
    elseif (cmd == 'C') then
      maxCmd_C(data)
    elseif (cmd == 'L') then
      maxCmd_L(data)
      break
    end
  end
 
  tcp:close()
 
end
 
return commandArray

Code: Select all

pi@raspberrypi:~/domoticz/scripts/lua$ lua maxtest.lua
Rooms
-----
Slaapkamer Johan        131498

Devices
-------
Slaapkamer Johan Rad    131498

Device status
-------------
Valve           Slaapkamer Johan Rad    Setpoint=16     Temp=0  Valve pos=0    Battery=OK       Mode=Manual
mvzut
Posts: 443
Joined: Thursday 12 November 2015 10:55
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: The Netherlands
Contact:

ELV Max! Heating control system

Post by mvzut »

YOYO wrote:Hello all,

It seems i have almost the script running although sending a setpoin by domoticz isnt working.
Furthermore there is an error occuring when im running the script but that seems to be time related i guess:

Code: Select all

2016-11-16 22:20:00.846 Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_time_max.lua: /home/pi/domoticz/scripts/lua/script_time_max.lua:21: bad argument #1 to 'sub' (string expected, got nil)
The script i have is not the last one mentioned in this thread but its the code thats actually on the WIKI page now.
I dont have a WMT (I have a RFX thermometer) so im bound to the valve reading and the setpoint from domoticz.

Who can help me out??
Is the name of you Domoticz thermostat "Slaapkamer Johan-Stat"? It looks like it cannot find the device, which can indeed be the case if the naming is not exactlly right. That could also explain the error message you show. The otherdevices_lastupdate value of the device is nil (since the device doesn't exist), therefore the age function gives an error since it calculates the age from an empty time string.

It seems you also haven't named the device correctly in the MAX! software, there should be a hyphen between Johan and Rad, so it should read "Slaapkamer Johan-Rad". You also have to rename the percentage device in Domoticz then to the same name.

P.S. You can also use the alternative script if you want, either as script_time_max.lua script executed by Domoticz (see http://www.domoticz.com/forum/viewtopic ... 00#p103332) or the maxscript.lua in the post below that is executed outside of Domoticz. In this way, it doesn't matter how you name your devices (after they have automatically been created).
Last edited by mvzut on Thursday 17 November 2016 9:57, edited 6 times in total.
Raspberry Pi 4 - RFXtrx433 - CC2531 Zigbee - Opentherm Gateway - P1 smart meter - Netatmo - Philips Hue - ELV Max! - ESP8266 DIY water meter - 6 x Sonos - 4 x IP cameras - Wall mounted tablet + Dashticz - Google Home integration - MANY switches/sensors
mvzut
Posts: 443
Joined: Thursday 12 November 2015 10:55
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: The Netherlands
Contact:

ELV Max! Heating control system

Post by mvzut »

blackdog65 wrote:
mvzut wrote:If you also want to try this, and my instructions are too sparse for you, let me know, so that I can explain in more detail.
I'm in the same situation. Everything runs like a "Swiss Watch" except for these time out errors, so I'd really like to see what you've done :D

Sean
Hi Sean,

Here is a version of the script that can be run outside of Domoticz using crontab (you may not recognise it at first, I polished it up quite a bit):

Code: Select all

-- Script which creates & synchronizes devices in Domoticz with values from MAX! cube
-- Change variables below to your own values
-- Start by adding new cronjob "*/5 * * * * /usr/bin/lua /home/pi/domoticz/scripts/lua/maxscript.lua" (using crontab -e) 

MaxIP='192.168.178.46' -- IP adress of your Cube, best to check via your router
MaxPort = 62910        -- Port used by your Cube, usually 62910
DomoticzPort = 8080    -- Port used by Domoticz, 8080 is the default
useWMT = true          -- Set to true if there is a wall mounted thermostat in every room
interval = 5           -- Polling interval in minutes, fill in same value as in crontab
setpoint_DoorOpen = 5  -- Setpoint when door/window open

json   = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()  -- uncomment if you're using Linux (comment next line)
--json = (loadfile "D:\\Domoticz\\scripts\\lua\\json.lua")()    -- uncomment if you're using Windows (comment previous line)

----------------------------------------
-- No changes required below this line -
----------------------------------------

package.loadlib("core.so", "*")
Socket = require "socket"
Basexx = require "basexx"
http   = require "socket.http"

Rooms   = {}
Devices = {}
Types   = {}
Room_nums = {}

function age(timestring)
  t = {}
  t.year = string.sub(timestring,1,4)
  t.month = string.sub(timestring,6,7)
  t.day = string.sub(timestring,9,10)
  t.hour = string.sub(timestring,12,13)
  t.min = string.sub(timestring,15,16)
  t.sec = string.sub(timestring,18,19)
  return os.difftime(os.time(),os.time(t))
end

function get_MAX_ID()
  result, statuscode, content = http.request('http://127.0.0.1:'..DomoticzPort..'/json.htm?type=hardware')
  r,e = json:decode(result)
  if r.status == "OK" then
    for k,v in pairs(r.result) do
      if v.Name == "MAX!" then return v.idx end
    end
  end
end

function ReadThermostat(DID)
  result, statuscode, content = http.request('http://127.0.0.1:'..DomoticzPort..'/json.htm?type=devices')
  r,e = json:decode(result)
  if r.status == "OK" then
    for k,v in pairs(r.result) do
      if v.ID == DID then return v.SetPoint,v.LastUpdate end
    end
  end
  return 0, '2016-01-01 00:00:00'  -- value to return if device was not found
end

function UpdateValve(DID, value)
  http.request('http://127.0.0.1:'..DomoticzPort..'/json.htm?type=command&param=udevice&hid='..MAX_ID..'&did='..DID..'&dunit=1&dtype=243&dsubtype=6&nvalue=0&svalue='..value)
end

function UpdateTemperature(DID, value)
  http.request('http://127.0.0.1:'..DomoticzPort..'/json.htm?type=command&param=udevice&hid='..MAX_ID..'&did='..DID..'&dunit=1&dtype=80&dsubtype=5&nvalue=0&svalue='..value)
end

function UpdateSwitch(DID, status)
  if status == "On" then
    http.request('http://127.0.0.1:'..DomoticzPort..'/json.htm?type=command&param=udevice&hid='..MAX_ID..'&did='..DID..'&dunit=1&dtype=17&dsubtype=0&nvalue=1')
  elseif status == "Off" then
    http.request('http://127.0.0.1:'..DomoticzPort..'/json.htm?type=command&param=udevice&hid='..MAX_ID..'&did='..DID..'&dunit=1&dtype=17&dsubtype=0&nvalue=0')
  end
end

function SetpointSync(DID, devicename, setpoint_MAX)
  setpoint_Domoticz, LastUpdate = ReadThermostat(DID)
  if tonumber(setpoint_Domoticz) ~= setpoint_MAX then
    if age(LastUpdate) > interval * 60 then -- Domoticz thermostat value must be updated
      http.request('http://127.0.0.1:'..DomoticzPort..'/json.htm?type=command&param=udevice&hid='..MAX_ID..'&did='..DID..'&dunit=1&dtype=242&dsubtype=1&nvalue=0&svalue='..setpoint_MAX)
      print(os.date("%x %X ")..'Domoticz setpoint '..devicename..' set to '..setpoint..' degrees')
      http.request('http://127.0.0.1:'..DomoticzPort..'/json.htm?type=command&param=addlogmessage&message='..string.gsub('Domoticz setpoint '..devicename..' set to '..setpoint_MAX..' degrees',' ','%%20'))
    elseif setpoint_Domoticz ~= setpoint_DoorOpen then -- MAX! setpoint must be updated
      MaxCmdSend(adr, room_num, "MANUAL", setpoint_Domoticz)
      print(os.date("%x %X ")..'MAX! setpoint '..devicename..' set to '..setpoint_Domoticz..' degrees')
      http.request('http://127.0.0.1:'..DomoticzPort..'/json.htm?type=command&param=addlogmessage&message='..string.gsub('MAX! setpoint '..devicename..' set to '..setpoint_Domoticz..' degrees',' ','%%20'))
    end
  end
end

function maxCmd_H(data)
--   print('H='..data)
end

function maxCmd_M(data)
  i = 0
  j = 0
  while true do    -- find next comma
    i = string.find(data, ",", i+1)
    if not i then break end
    j = i
  end
  s   = data:sub(j+1)
  dec = Basexx.from_base64(s)
  num_rooms = string.byte(dec,3)
  
  if num_rooms == 0 or num_rooms == nil then
    http.request('http://127.0.0.1:'..DomoticzPort..'/json.htm?type=command&param=addlogmessage&message=MAX!%20configuration%20error!')
  end
  
  pos=4
  for i=1, num_rooms do
    room_num = string.byte(dec, pos)
    name_len = string.byte(dec, pos+1)
    pos  = pos+2
    name = dec:sub(pos, pos+name_len-1)
    pos  = pos+name_len
    adr  = Basexx.to_hex(dec:sub(pos, pos+2))
    Rooms[room_num] = name
    pos = pos+3
  end
      
  num_devs = string.byte(dec, pos)
  for i=1, num_devs do
    dtype = string.byte(dec, pos+1)
    adr   = Basexx.to_hex(dec:sub(pos+2, pos+4))
    snum  = dec:sub(pos+5, pos+14)
    name_len = string.byte(dec, pos+15)
    pos  = pos+16
    name = dec:sub(pos, pos+name_len-1)
    pos  = pos+name_len
    room_num = string.byte(dec, pos)
    Room_nums[adr] = room_num
    Devices[adr] = name
    Types[adr] = dtype
  end
end

function maxCmd_C(data)
--   print('C='..data)
end

function maxCmd_L(data)
  pos = 1
  dec = Basexx.from_base64(data)
  L_hex = Basexx.to_hex(dec)
  L_len = string.len(L_hex)
   
  while (pos < L_len) do

    s = L_hex:sub(pos,(pos+1))
    data_len  = tonumber(s,16) + 1
    hex  = L_hex:sub(pos, pos+(data_len*2))
    adr  = hex:sub(3,8)
    room_num = string.format("%02X", Room_nums[adr])
    room = Rooms[Room_nums[adr]]
    name = Devices[adr]
    dtype = Types[adr]
    if not name then name=adr end
    valve_info = tonumber(hex:sub(13,14),16)
    batt = bit32.extract(valve_info,7,1)
    bst  = bit32.extract(valve_info,3,1)
    mode = bit32.extract(valve_info,0,2)
      
    if (batt==0) then sbat="OK" else sbat="Low" end
    if (mode==0) then smode="Auto" elseif (mode==1) then smode="Manual"
    elseif (mode==2) then smode="Holiday" elseif (mode==3) then smode="Boost" end
      
    if dtype == 3 then	-- WallMountedThermostat
      s = hex:sub(17,18)
      setpoint = tonumber(s,16) / 2
      if setpoint > 50 then setpoint = setpoint - 64 end
      s = hex:sub(23,26)
      temp = tonumber(s,16) / 10
      if temp < 5 then temp = temp + 25.5 end  -- temporary solution for 2 digit hex temperature limitation
      UpdateTemperature(adr, temp)
      SetpointSync('0'..adr, name, setpoint)

    elseif dtype == 1 or dtype == 2 then -- Valve
      s = hex:sub(15,16)
      valve_pos = tonumber(s,16)
      s = hex:sub(17,18)
      setpoint = tonumber(s,16) / 2
      if setpoint > 50 then setpoint = setpoint - 64 end
      s = hex:sub(19,22)
      temp = tonumber(s,16) / 10
      if temp < 5 then temp = temp + 25.5 end  -- temporary solution for 2 digit hex temperature limitation
      UpdateValve(adr, valve_pos)
      if not useWMT then -- Use valve for temp & setpoint
        if temp ~= 0 then UpdateTemperature(adr, temp) end
        SetpointSync('0'..adr, name, setpoint)
      end

    elseif dtype == 4 then -- Door/window sensor
      if mode == 2 then UpdateSwitch(adr, "On") else UpdateSwitch(adr, "Off") end
    end

    pos = pos + (data_len*2)

  end
end

function MaxCmdSend(id, room, mode, setpoint)
   bits  = setpoint * 2
   smode = string.upper(mode)
   if smode == 'MANUAL' then
      bits = 64 + bits
   elseif smode == 'BOOST' then
      bits = 192 + bits
   elseif smode == 'VACATION' then
      bits = 128 + bits
   end
   hex = "000440000000"..id..room..string.format("%x",bits)
   sendStr = Basexx.to_base64(Basexx.from_hex(hex))
   i, status = tcp:send("s:"..sendStr.."\r\n")
   if not i then
      print("MAX TCP send failed - "..status)
      return
   end
end

-----------------------
-- Main script start --
-----------------------

  --Get ID of MAX hardware in Domoticz, create if it doesn't exist
  MAX_ID = get_MAX_ID()
  if MAX_ID == nil then  -- "MAX!" dummy hardware not yet created, create it
    http.request('http://127.0.0.1:'..DomoticzPort..'/json.htm?type=command&param=addhardware&htype=15&port=1&name=MAX!&enabled=true')
  end

  tcp = Socket.connect(MaxIP, MaxPort)
  if not tcp then
    print("Socket connect failed for "..MaxIP..':'..MaxPort)
    return
  end
  tcp:settimeout(2)

  while true do
    s, status, partial = tcp:receive()
    if (status) then
      print("TCP receive - "..status)
     break
    end
      
    local line = (s or partial)
    local cmd  = line:sub(1,1)
    local data = line:sub(3)
   
    if (cmd == 'H') then
      status = maxCmd_H(data)
      if status == 'Error' then break end
    elseif (cmd == 'M') then
      maxCmd_M(data)
    elseif (cmd == 'C') then
      maxCmd_C(data)
    elseif (cmd == 'L') then
      maxCmd_L(data)
      break
    end
  end

  tcp:close()
You can place it in /home/pi/domoticz/scripts/lua/ but then with a different name, e.g. maxscript.lua, so that Domoticz is not going to run it every minute. You need to remove the "old" script or rename it to script_time_max.lua.disabled or something.

After you have done this, start an SSH terminal session to your Raspberry Pi (provided your Domoticz runs on a Raspberry Pi). Start the crontab editor with

Code: Select all

sudo crontab -e
and add this line to the bottom of the file:

Code: Select all

*/5 * * * * /usr/bin/lua /home/pi/domoticz/scripts/lua/maxscript.lua
(replace script name if you used something else than my suggestion).

Press control+X, Y and enter, and off you go!

P.S. It may also work with crontab -e, i.e. without the sudo, but I use this and it works.

UPDATE 3-12-2016 11:19
I implemented door/window sensor reading in this one, switches will be automatically created for them. Just add & name them via the devices screen, and then change the switch type to "contact". Also set the vairable "setpoint_DoorOpen" to what you configured for this in MAX! This will prevent that the temporarily reduced setpoint is written back to MAX! as permanent new setpoint.
Last edited by mvzut on Saturday 03 December 2016 11:19, edited 14 times in total.
Raspberry Pi 4 - RFXtrx433 - CC2531 Zigbee - Opentherm Gateway - P1 smart meter - Netatmo - Philips Hue - ELV Max! - ESP8266 DIY water meter - 6 x Sonos - 4 x IP cameras - Wall mounted tablet + Dashticz - Google Home integration - MANY switches/sensors
Skippiemanz
Posts: 230
Joined: Sunday 14 July 2013 20:21
Target OS: Linux
Domoticz version: 4.10233
Location: Alkmaar, The Netherlands
Contact:

Re: ELV Max! Heating control system

Post by Skippiemanz »

There seems to be a new lua setpoint update command.. Maybe helpful? viewtopic.php?p=104806#p104806
Last edited by Skippiemanz on Sunday 20 November 2016 12:24, edited 1 time in total.
mvzut
Posts: 443
Joined: Thursday 12 November 2015 10:55
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: The Netherlands
Contact:

ELV Max! Heating control system

Post by mvzut »

Skippiemanz wrote:There seems to be a new lua setpoint update command.. Maybe helpful? https://www.domoticz.com/forum
/viewtopic.php?p=104806#p104806
Interesting, thanks for (set)pointing this out! Image
I will test and change the script in the Wiki if it works. Could result in faster script execution and therefore less timeout errors. It will probably not be a solution for the timeout errors of the alternative script. But these can perfectly be solved by running it outside Domoticz, see previous post.

Anyone still interested in reading out door/window sensors? I managed to get it working. I'll add it to the Wiki when I can find the time (probably not today, sorry...). If you want to expereriment already now, try the solution in my previous post.
Raspberry Pi 4 - RFXtrx433 - CC2531 Zigbee - Opentherm Gateway - P1 smart meter - Netatmo - Philips Hue - ELV Max! - ESP8266 DIY water meter - 6 x Sonos - 4 x IP cameras - Wall mounted tablet + Dashticz - Google Home integration - MANY switches/sensors
Skippiemanz
Posts: 230
Joined: Sunday 14 July 2013 20:21
Target OS: Linux
Domoticz version: 4.10233
Location: Alkmaar, The Netherlands
Contact:

Re: RE: ELV Max! Heating control system

Post by Skippiemanz »

mvzut wrote: Anyone still interested in reading out door/window sensors? I managed to get it working. I'll add it to the Wiki when I can find the time (probably not today, sorry...). If you want to expereriment already now, try the solution in my previous post.
Count me in! I will try it later today! Does it show the state of the window/door sensors?
mvzut
Posts: 443
Joined: Thursday 12 November 2015 10:55
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: The Netherlands
Contact:

ELV Max! Heating control system

Post by mvzut »

Skippiemanz wrote:Count me in! I will try it later today! Does it show the state of the window/door sensors?
Yes it does! Be aware that it's not really useful for security/alarm purposes, since the sensors are not updated instantly but only every so many minutes (depending on how you set the interval). But you could use it to be reminded if you left a door or window open when nobody is home.
Raspberry Pi 4 - RFXtrx433 - CC2531 Zigbee - Opentherm Gateway - P1 smart meter - Netatmo - Philips Hue - ELV Max! - ESP8266 DIY water meter - 6 x Sonos - 4 x IP cameras - Wall mounted tablet + Dashticz - Google Home integration - MANY switches/sensors
YOYO
Posts: 27
Joined: Tuesday 09 June 2015 21:22
Target OS: Raspberry Pi / ODroid
Domoticz version: V2.23393
Location: The Netherlands
Contact:

Re: ELV Max! Heating control system

Post by YOYO »

Hi Mvzut,

I have read youre post and have changed the device names to the ones used in youre scripts.
Although something strange happened last night.

It seems that around 04:00 domoticz stopped working for some reason so i have restarted the raspberry just now.
Unfortunally it seems that something broke during executing the scripts resulting in the following errors:

Code: Select all

2016-11-18 19:52:07.559 LUA: Socket connect failed for 192.168.1.152:62910
2016-11-18 19:52:18.071 Error: PROXY: Connect failed, reconnecting: Operation canceled
I have checked with the MAX! app but the cube is running on the adress named.
Could it be that the cube has changed ports overnight?
YOYO
Posts: 27
Joined: Tuesday 09 June 2015 21:22
Target OS: Raspberry Pi / ODroid
Domoticz version: V2.23393
Location: The Netherlands
Contact:

Re: ELV Max! Heating control system

Post by YOYO »

Hmm seems the crash of last night corruppted the script.
I removed the script and uploaded the script from the wiki again in a new file and voila works as before! :D
Teatech
Posts: 22
Joined: Sunday 22 November 2015 11:10
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.5877
Location: Finland
Contact:

Re: ELV Max! Heating control system

Post by Teatech »

mvzut wrote: Here is a version of the script that can be run outside of Domoticz using crontab:
How this separate script effects previous Domoticz script devices? Will they remain the same? I want to try that but I don't want to mess old device readings. And that old script seems to work just fine (if you don't count those "timeout" errors).
mvzut
Posts: 443
Joined: Thursday 12 November 2015 10:55
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: The Netherlands
Contact:

ELV Max! Heating control system

Post by mvzut »

Teatech wrote:
mvzut wrote: Here is a version of the script that can be run outside of Domoticz using crontab:
How this separate script effects previous Domoticz script devices? Will they remain the same? I want to try that but I don't want to mess old device readings. And that old script seems to work just fine (if you don't count those "timeout" errors).
Yes, the devices will stay the same (assuming you are already using the auto-device-creation script). So you can easily switch between the two scripts.

I have it running for almost two days now, and I love having a clean log again! I really believe this is ultimately the best architecture, especially if you have more than a handful of MAX! devices. Scripts that run inside Domoticz will always be prone to timeout errors in large systems.
Raspberry Pi 4 - RFXtrx433 - CC2531 Zigbee - Opentherm Gateway - P1 smart meter - Netatmo - Philips Hue - ELV Max! - ESP8266 DIY water meter - 6 x Sonos - 4 x IP cameras - Wall mounted tablet + Dashticz - Google Home integration - MANY switches/sensors
Teatech
Posts: 22
Joined: Sunday 22 November 2015 11:10
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.5877
Location: Finland
Contact:

Re: ELV Max! Heating control system

Post by Teatech »

Ok, thanks. Number of devices certanly effects to number of errors but I still have 3 devices that I'm testing system and I receive those errors.
Maybe I test external script before I add those 12 valves. If you're correct number of errors will otherwise increase alot.
jmbjmbjmb
Posts: 48
Joined: Monday 25 January 2016 10:41
Target OS: -
Domoticz version:
Contact:

Re: ELV Max! Heating control system

Post by jmbjmbjmb »

I am a bit confused with the naming convention and the dummy devices in domoticz (which I am new to).
Basically, I have 1 room with a wall thermostat and 2 thermostats. All other rooms do not have wall thermostats.
Using the Max GUI, I have set all my radiators with a "-Rad" suffix. The only room where I have a wall thermostat is also set with a "-Stat" suffix. Since the two rads in that room can not have the same name, I have named them something like roomNorth-Rad and roomSouth-Rad with the wall thermostat being name room-Stat. I could not do it any differently but I am not sure if that complies with what is expected.

Second issue, I have started creating devices in domoticz and this is confusing me a bit. So basically, for a room that has no wall thermostat, my understanding is that I should do the following:
- From the Setup>Hardware menu, create (e.g., for the kitchen), 3 dummy devices:
- Kitchen
- Kitchen-Rad
- Kitchen-Stat
- Then, for each I would click on "Create virtual sensors"
- When clicking on "creating virtual sensors" for Kitchen, I would fill the name with "Kitchen" and select Temperature and click OK
- for Kitchen-Rad I would fill Kitchen-Rad in and select Percentage
- and for Kitchen-Stat I would put Kitchen-Rad and select Thermostat setpoint (and if I had had a wall thermostat then I would have filled the name field with Kitchen-Stat instead)

Is that correct ? And, if so, how do I deal with the room that has 1 wall thermostat and 2 radiators ?

Thanks
mvzut
Posts: 443
Joined: Thursday 12 November 2015 10:55
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: The Netherlands
Contact:

ELV Max! Heating control system

Post by mvzut »

jmbjmbjmb wrote:I am a bit confused with the naming convention and the dummy devices in domoticz (which I am new to).
Basically, I have 1 room with a wall thermostat and 2 thermostats. All other rooms do not have wall thermostats.
Using the Max GUI, I have set all my radiators with a "-Rad" suffix. The only room where I have a wall thermostat is also set with a "-Stat" suffix. Since the two rads in that room can not have the same name, I have named them something like roomNorth-Rad and roomSouth-Rad with the wall thermostat being name room-Stat. I could not do it any differently but I am not sure if that complies with what is expected.

Second issue, I have started creating devices in domoticz and this is confusing me a bit. So basically, for a room that has no wall thermostat, my understanding is that I should do the following:
- From the Setup>Hardware menu, create (e.g., for the kitchen), 3 dummy devices:
- Kitchen
- Kitchen-Rad
- Kitchen-Stat
- Then, for each I would click on "Create virtual sensors"
- When clicking on "creating virtual sensors" for Kitchen, I would fill the name with "Kitchen" and select Temperature and click OK
- for Kitchen-Rad I would fill Kitchen-Rad in and select Percentage
- and for Kitchen-Stat I would put Kitchen-Rad and select Thermostat setpoint (and if I had had a wall thermostat then I would have filled the name field with Kitchen-Stat instead)

Is that correct ? And, if so, how do I deal with the room that has 1 wall thermostat and 2 radiators ?

Thanks
It should work the way you describe it. Plus you have to set the "useWMT" variable to false.

If you are confused or have problems getting things to work, I can definitely advise my latest variant of the script. This is a lua file that periodically runs outside Domoticz and creates all devices automatically. They appear as unused devices, which you can give any name you want when adding them as used device (using the green arrow buttons in the Devices screen).

Running the script outside Domoticz sounds more complicated than it is, only a few commands in an SSH terminal are required (crontab -e and then adding one line at the bottom of the file). After that, it can take up to two cycles (of each 5 minutes, if you use the default interval) before the devices appear.

See a few posts back for the script and a simple guide on how to install it. This script works extremely stable at my side for quite some time already, and it's the easiest of them all to install.
Last edited by mvzut on Friday 25 November 2016 23:43, edited 2 times in total.
Raspberry Pi 4 - RFXtrx433 - CC2531 Zigbee - Opentherm Gateway - P1 smart meter - Netatmo - Philips Hue - ELV Max! - ESP8266 DIY water meter - 6 x Sonos - 4 x IP cameras - Wall mounted tablet + Dashticz - Google Home integration - MANY switches/sensors
User avatar
blackdog65
Posts: 311
Joined: Tuesday 17 June 2014 18:25
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Norfolk, UK
Contact:

Re: ELV Max! Heating control system

Post by blackdog65 »

In addition to mvzut's reply, the naming convention ONLY applies if you want to use the second script automate your heating.

if so
how do I deal with the room that has 1 wall thermostat and 2 radiators

Xroom + Xroom-Stat + Xroom1-Rad + Xroom2-Rad should work. Or XroomL-Rad + XroomR-Rad
CubieTruck Master
RasPi slaves
Aeon Labs Z-Stick, multi sensor
Fibaro Dimmers, relays, Universal sensors
EQ3 MAX!
TKB Sockets
RFXCOM
LightwaveRF sockets, switches, relays, doorbell
MySensors
ESPEasy ESP8266-12E
jmbjmbjmb
Posts: 48
Joined: Monday 25 January 2016 10:41
Target OS: -
Domoticz version:
Contact:

Re: ELV Max! Heating control system

Post by jmbjmbjmb »

Hi,

I tried the script but it is referring to a json.lua which is not installed by default. Where can I get that file ?
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests