Hi,
Would it be possible to add a 3 phase voltage device, similar to the 3 phase current device? It is a bit clumsy to have 3 individual devcices for Voltage where the one for current is much more elegant
Request: 3 phase voltage device
Moderators: leecollings, remb0
-
JanJaap
- Posts: 245
- Joined: Thursday 12 October 2017 20:46
- Target OS: Raspberry Pi / ODroid
- Domoticz version: Dev
- Location: the Netherlands
- Contact:
Request: 3 phase voltage device
RPi 3, Domoticz dev version, Aeon ZWave stick (with a whole bunch of slaves), Zigbee using Zigbee2MQTT, Nest thermo, P1 smart meter on RPi Zero
- imautohuttraeger
- Posts: 405
- Joined: Saturday 14 March 2020 13:40
- Target OS: Raspberry Pi / ODroid
- Domoticz version: latest
- Location: Germany
- Contact:
Re: Request: 3 phase voltage device
Good Point. I also miss this. And 3 phase power devices would also be helpful.
Stop, look and listen.
- RonkA
- Posts: 142
- Joined: Tuesday 14 June 2022 12:57
- Target OS: NAS (Synology & others)
- Domoticz version: 2025.1
- Location: Harlingen
- Contact:
Re: Request: 3 phase voltage device
Not what you are asking exactly but this is my good old text-device workaround.. Maybe an inspiration for Gizmocuz
The script is usable for 1,2 and 3 phase voltages.. it gives this:
Before use Read! and adjust all devices marked by -->-->-->- (so 5 things..) in the script!!
Last one is specific; i run Domoticz in a Docker container on my Synology-nas, I don't know your ip-adres and port, (could be as simple as 192.168.1.xxx:80)
The script is usable for 1,2 and 3 phase voltages..
Code: Select all
-- Voltage Bargraph maker for text device -- RonkA
return {
on = {
timer = {'at 23:59'},
devices = {27} -->-->-->- set correct idx number of P1_device
},
data = {
min_voltage_L1 = { initial = 229.9 }, -- Initialize the min_voltage_L1 variable; for 120v mains set to 119.9
min_voltage_L2 = { initial = 229.9 }, -- Initialize the min_voltage_L2 variable; for 120v mains set to 119.9
min_voltage_L3 = { initial = 229.9 }, -- Initialize the min_voltage_L3 variable; for 120v mains set to 119.9
max_voltage_L1 = { initial = 230 }, -- Initialize the max_voltage_L1 variable; for 120v mains set to 120.1
max_voltage_L2 = { initial = 230 }, -- Initialize the max_voltage_L2 variable; for 120v mains set to 120.1
max_voltage_L3 = { initial = 230 }, -- Initialize the max_voltage_L3 variable; for 120v mains set to 120.1
},
--[[ logging = {
level = domoticz.LOG_ERROR,
marker = 'Bargraph',
},
]]
execute = function(domoticz, device)
-->-->-->- values are set for 230 volt mains with a 10% tolerance according to NEN-EN 50160
-- for 120 volt mains with a 5% tolerance (ANSI standard) adjust values accordingly
-- domoticz.log('Bargraph - Net - Voltages ' .. device.name, domoticz.LOG_INFO)
local padding = 7 -- number of invisible blocks to allign the 2nd and 3rd bargraph in the textdevice
local bar_length = 17 -- number of segments in bargraph - for 120 volts mains
local low_value = 207 -- begin value of the low red zone - 114
local low_red_value = 212 -- value to start the low red zone - 116
local low_yellow_value = 220 -- value to start the low yellow zone - 118
local mid_value = 230 -- middle of green zone - 120
local high_yellow_value = 240 -- value to start the high yellow zone - 122
local high_red_value = 248 -- value to start the high red zone - 124
local high_value = 253 -- end value of the high red zone - 126
-- fictional values if less than 3 phase are used.. do not remove!
local voltageL2 = 231
local voltageL3 = 231
-->-->-->- for 1 phase metering only use voltageL1; voltageL2 and voltageL3 have to be commented out! (set -- in front of local..)
-- for 2 phase metering only use voltageL1 and voltageL2; voltageL3 has to be commented out!
-- set correct idx number of voltage device(s)
local voltageL1 = domoticz.utils.round(domoticz.devices(28).voltage,1)
local voltageL2 = domoticz.utils.round(domoticz.devices(29).voltage,1)
local voltageL3 = domoticz.utils.round(domoticz.devices(30).voltage,1)
-->-->-->- idx number of the textdevice; change accordingly
local text_device = domoticz.devices(337)
-- initialize min and max voltage values
local voltageL1_min = domoticz.data.min_voltage_L1
local voltageL2_min = domoticz.data.min_voltage_L2
local voltageL3_min = domoticz.data.min_voltage_L3
local voltageL1_max = domoticz.data.max_voltage_L1
local voltageL2_max = domoticz.data.max_voltage_L2
local voltageL3_max = domoticz.data.max_voltage_L3
-- store value when voltage is lower or higer than the stored min or max voltage
if voltageL1 < mid_value and voltageL1 < voltageL1_min then
domoticz.data.min_voltage_L1 = voltageL1
end
if voltageL2 < mid_value and voltageL2 < voltageL2_min then
domoticz.data.min_voltage_L2 = voltageL2
end
if voltageL3 < mid_value and voltageL3 < voltageL3_min then
domoticz.data.min_voltage_L3 = voltageL3
end
if voltageL1 > mid_value and voltageL1 > voltageL1_max then
domoticz.data.max_voltage_L1 = voltageL1
end
if voltageL2 > mid_value and voltageL2 > voltageL2_max then
domoticz.data.max_voltage_L2 = voltageL2
end
if voltageL3 > mid_value and voltageL3 > voltageL3_max then
domoticz.data.max_voltage_L3 = voltageL3
end
-- check if it's nighttime (23:59) to reset bargraph variables
if (device.isTimer) then
domoticz.log('Reset Bargraph Voltage Variables', domoticz.LOG_INFO)
domoticz.data.min_voltage_L1 = 229.9
domoticz.data.min_voltage_L2 = 229.9
domoticz.data.min_voltage_L3 = 229.9
domoticz.data.max_voltage_L1 = 230
domoticz.data.max_voltage_L2 = 230
domoticz.data.max_voltage_L3 = 230
return
end
-- function to take (value) and make half a bargraph in the correct manner.
--if value is lower than mid_value bargraph from right to left and if value is higher than mid_value from left to right
local function createBargraph(value)
local one_segment = (high_value - low_value) / (2 * bar_length)
local low_green_zone = math.abs(math.floor((low_yellow_value - mid_value) / one_segment))
local low_yellow_zone = math.abs(math.floor((low_red_value - mid_value) / one_segment))
local low_red_zone = bar_length
local high_green_zone = math.floor((high_yellow_value - mid_value) / one_segment)
local high_yellow_zone = math.floor((high_red_value - mid_value) / one_segment)
local high_red_zone = bar_length
local text_value = value
-- stop value to get lower or higher than outer values of bargraph
if value < low_value then
value = low_value
elseif value > high_value then
value = high_value
end
-- determine if value is lower or higer than mid_value
local segment_count = math.abs(math.floor((value - mid_value) / one_segment))
local is_below_mid = value < mid_value
local bar = ''
if is_below_mid then
segment_count_low = bar_length - math.floor((mid_value - value) / one_segment)
-- building the separate bar segments when value is lower than mid_value
local green_bar = ''
local yellow_bar = ''
local red_bar = ''
if segment_count_low > low_red_zone then
green_bar = '<span style="color: green;">' .. string.rep('■', low_green_zone) .. '</span>'
yellow_bar = '<span style="color: yellow">' .. string.rep('■', low_yellow_zone - low_green_zone) .. '</span>'
red_bar = '<span style="color: Red;">' .. string.rep('■', low_red_zone - low_yellow_zone) .. '</span>'
elseif segment_count_low > low_green_zone then
green_bar = '<span style="color: #CCFDA9 ;">' .. string.rep('■', low_green_zone - segment_count) .. '</span>' ..
'<span style="color: Green;">' .. string.rep('■', segment_count) .. '</span>'
yellow_bar = '<span style="color: #F4FDA9 ;">' .. string.rep('■', low_yellow_zone - low_green_zone) .. '</span>'
red_bar = '<span style="color: #FDD2A9;">' .. string.rep('■', low_red_zone - low_yellow_zone) .. '</span>'
elseif segment_count_low <= low_green_zone and segment_count_low > low_yellow_zone - low_green_zone then
green_bar = '<span style="color: Green;">' .. string.rep('■', low_green_zone) .. '</span>'
yellow_bar = '<span style="color: #F4FDA9 ;">' .. string.rep('■', low_yellow_zone - segment_count) .. '</span>' ..
'<span style="color: Yellow;">' .. string.rep('■', segment_count - low_green_zone) .. '</span>'
red_bar = '<span style="color: #FDD2A9;">' .. string.rep('■', low_red_zone - low_yellow_zone) .. '</span>'
elseif segment_count_low <= low_red_zone - low_yellow_zone then
green_bar = '<span style="color: Green;">' .. string.rep('■', low_green_zone) .. '</span>'
yellow_bar = '<span style="color: Yellow;">' .. string.rep('■', low_yellow_zone - low_green_zone) .. '</span>'
red_bar = '<span style="color: #FDD2A9;">' .. string.rep('■', low_red_zone - segment_count) .. '</span>' ..
'<span style="color: Red;">' .. string.rep('■', segment_count - low_yellow_zone) .. '</span>'
end
-- assemble bar
bar = '◄' .. red_bar .. yellow_bar .. green_bar .. '►'
else
-- Building the separate bar segments when value is higher than mid_value
local green_bar = ''
local yellow_bar = ''
local red_bar = ''
if segment_count <= high_green_zone then
green_bar = '<span style="color: Green;">' .. string.rep('■', segment_count) .. '</span>' ..
'<span style="color: #CCFDA9 ;">' .. string.rep('■', high_green_zone - segment_count) .. '</span>'
yellow_bar = '<span style="color: #F4FDA9 ;">' .. string.rep('■', high_yellow_zone - high_green_zone) .. '</span>'
red_bar = '<span style="color: #FDD2A9 ;">' .. string.rep('■', high_red_zone - high_yellow_zone) .. '</span>'
elseif segment_count > high_green_zone and segment_count <= high_yellow_zone then -- 13>7= ok 13<=11=not
green_bar = '<span style="color: Green;">' .. string.rep('■', high_green_zone) .. '</span>'
yellow_bar = '<span style="color: Yellow;">' .. string.rep('■', segment_count - high_green_zone) .. '</span>' ..
'<span style="color: #F4FDA9 ;">' .. string.rep('■', high_yellow_zone - segment_count) .. '</span>'
red_bar = '<span style="color: #FDD2A9 ;">' .. string.rep('■', high_red_zone - high_yellow_zone) .. '</span>'
elseif segment_count > high_yellow_zone then --13>11=ok
green_bar = '<span style="color: Green;">' .. string.rep('■', high_green_zone) .. '</span>'
yellow_bar = '<span style="color: Yellow;">' .. string.rep('■', high_yellow_zone - high_green_zone) .. '</span>'
red_bar = '<span style="color: Red;">' .. string.rep('■', segment_count - high_yellow_zone) .. '</span>' ..
'<span style="color: #FDD2A9 ;">' .. string.rep('■', high_red_zone - segment_count) .. '</span>'
elseif segment_count > high_red_zone then
green_bar = '<span style="color: Green;">' .. string.rep('■', high_green_zone) .. '</span>'
yellow_bar = '<span style="color: Yellow;">' .. string.rep('■', high_yellow_zone - high_green_zone) .. '</span>'
red_bar = '<span style="color: Red;">' .. string.rep('■', segment_count - high_yellow_zone) .. '</span>'
end
-- assemble bar
bar = '◄' .. green_bar .. yellow_bar .. red_bar .. '►'
end
return bar
end
-- the next 2 functions create the texts around the bargraph(s).
-- when the bar_length is altered or if there is a mismach between the bargraph and the numbers..
-- this can be adjusted by changing the number after the word 'segment_count'.. a lower value wil adjust to the left
-- the adjustment has to be done 4 times per function
-- an easy way to test is by giving a fixed known value to voltageL1 like 200; 229.9; 230,1; 260
-- something like: local voltageL1 = 200 --domoticz.utils.round(domoticz.devices(28).voltage,1) in the beginning of the script
-- after all done remove the '200 --' but that should be obvious...
-- resetting the bargraph can be done by removing bargraph volt.lua file from the domoticz\scripts\dzVents\data directory (in my docker enviroment..)
-- this can be helpfull to do after the adjustments as discribed above or if there was a power outage..
-- or just wait till the day is over, than all values are reset to the initial ones
-- function to get the bottom bar to be displayed at the correct place
local function create_bottom_bar(value_posd, blocks)
bottom_bar_arrow = ''
bottom_bar_value = ''
blockpad = string.rep(' ', blocks)
value = value_posd
-- stop value to get lower or higher than outer values of bargraph
if value_posd < mid_value and value_posd < low_value then
value_posd = low_value end
if value_posd > mid_value and value_posd > high_value then
value_posd = high_value end
local one_segment = (high_value - low_value) / (2 * bar_length)
local segment_count = math.abs(math.floor((value_posd - low_value) / one_segment))
if value_posd < mid_value then
-- when value_posd is lower than mid_value
if (segment_count - 2) < (bar_length / 2) then
-- value on right side of arrow like ▲ 218.4V
-- bar_length is 17 = segment_count + 1; + 1
-- bar_length is 15 = segment_count + 1; + 1
-- bar_length is 13 = segment_count + 1; + 1
bottom_bar_arrow = string.rep(' ', segment_count + 1) .. '▲'
bottom_bar_value = string.rep(' ', segment_count + 1) .. '⁞ <span style="background-color: Aquamarine;">' .. domoticz.utils.round(value ,1) .. 'V</span>'
else
-- value on left side of arrow like 228.7V ▲
-- bar_length is 17 = segment_count + 1; - 6
-- bar_length is 15 = segment_count + 1; - 6
-- bar_length is 13 = segment_count + 1; - 6
bottom_bar_arrow = string.rep(' ', segment_count + 1).. '▲'
bottom_bar_value = string.rep(' ', segment_count - 6) .. '<span style="background-color: Aquamarine;">' .. domoticz.utils.round(value,1) .. 'V</span> ⁞'
end
else
-- when value_posd is higher than mid_value
if bar_length >= segment_count - 6 then
-- value on right side of arrow like ▲ 231.3V
-- bar_length is 17 = segment_count + 5; + 5
-- bar_length is 15 = segment_count + 4; + 4
-- bar_length is 13 = segment_count + 4; + 4
bottom_bar_arrow = string.rep(' ', segment_count + 5) .. '▲'
bottom_bar_value = string.rep(' ', segment_count + 5) .. '⁞ <span style="background-color: Aquamarine;">' .. domoticz.utils.round(value,1) .. 'V</span>'
else
-- value on left side of arrow like 248.2V ▲
-- bar_length is 17 = segment_count + 4; - 3
-- bar_length is 15 = segment_count + 4; - 3
-- bar_length is 13 = segment_count + 4; - 3
bottom_bar_arrow = string.rep(' ', segment_count + 4) .. '▲'
bottom_bar_value = string.rep(' ', segment_count - 3) .. '<span style="background-color: Aquamarine;">' .. domoticz.utils.round(value,1) .. 'V</span> ⁞'
end
end
return blockpad .. bottom_bar_arrow .. '\n' .. blockpad .. bottom_bar_value
end
-- function to get the historic values to be displayed at the correct place swapping the place of the arrow and value if necessary
local function create_top_bar(value_posu)
-- stop value to get lower or higher than outer values of bargraph
value = value_posu
if value_posu < mid_value and value_posu < low_value then
value_posu = low_value end
if value_posu > mid_value and value_posu > high_value then
value_posu = high_value end
local one_segment = (high_value - low_value) / (2 * bar_length)
local segment_count = math.abs(math.floor((value_posu - low_value) / one_segment))
if value_posu < mid_value then
-- when value_posu is lower than mid_value
if segment_count < bar_length / 2 then
-- value on right side of arrow = ▼ 208.8
-- bar_length is 17 = segment_count + 1 and segment_count - 4
-- bar_length is 15 = segment_count + 1 and segment_count - 4
-- bar_length is 13 = segment_count + 1 and segment_count - 4
top_bar = string.rep(' ', segment_count + 1) .. '▼ ' .. domoticz.utils.round(value,1) .. 'V' .. string.rep(' ', (bar_length - segment_count) -4)
else
-- value on left side of arrow = 226.1V ▼
-- bar_length is 17 = segment_count - 6 and segment_count +3
-- bar_length is 15 = segment_count - 6 and segment_count +3
-- bar_length is 13 = segment_count - 6 and segment_count +3
top_bar = string.rep(' ', segment_count - 6) .. domoticz.utils.round(value,1) .. 'V ▼' .. string.rep(' ', (bar_length - segment_count) +3)
end
else
-- when value_posu is higher than mid_value
if bar_length >= segment_count - 8 then
-- value on right side of arrow = ▼ 241.8V
-- bar_length is 17 = segment_count - 18
-- bar_length is 15 = segment_count - 16
-- bar_length is 13 = segment_count - 14
top_bar = string.rep(' ', segment_count - 18) .. '▼ ' .. domoticz.utils.round(value,1) .. 'V'
else
-- value on left side of arrow = 250.5V ▼
-- bar_length is 17 = segment_count - 25
-- bar_length is 15 = segment_count - 23
-- bar_length is 13 = segment_count - 21
top_bar = string.rep(' ', segment_count - 25) .. domoticz.utils.round(value,1) .. 'V ▼'
end
end
return top_bar
end
-- create invisible blocks to allign the 2nd and 3rd bargraph in the textdevice
padd = string.rep(' ', padding)
-->-->-->- building bargraph
-- when using 1 phase comment the 2nd and 3rd "local bargraph" line out! (set -- in front of local..)
-- when using 2 phase comment the 3rd "local bargraph line" out!
local bargraph = create_top_bar(voltageL1_min) .. create_top_bar(voltageL1_max) .. '\n' .. createBargraph(voltageL1_min) .. 'L1' .. createBargraph(voltageL1_max) .. '\n' .. create_bottom_bar(voltageL1, 0) .. '\n'
local bargraph = bargraph ..'――――――――――――――――――――――――――――――――――――――――\n' .. padd .. create_top_bar(voltageL2_min) .. create_top_bar(voltageL2_max) .. '\n' .. padd .. createBargraph(voltageL2_min) .. 'L2' .. createBargraph(voltageL2_max) .. '\n' .. create_bottom_bar(voltageL2, padding) .. '\n'
local bargraph = bargraph .. padd .. '――――――――――――――――――――――――――――――――――――――――\n'.. padd .. create_top_bar(voltageL3_min) .. create_top_bar(voltageL3_max) .. '\n' .. padd .. createBargraph(voltageL3_min) .. 'L3' .. createBargraph(voltageL3_max) .. '\n'.. create_bottom_bar(voltageL3, padding)
-- giving the bargraph the correct font and settings
local final_bar = '<span style="font-family: Consolas; font-weight: bold; font-size: 13px;">' .. bargraph .. '</span>'
-- update text_device
text_device.updateText(final_bar)
-->-->-->- Clear the log of the textdevice, put in the right idx of the textdevice!!
domoticz.openURL('http://127.17.0.2:80/json.htm?type=command¶m=clearlightlog&idx=337')
end
}
Last one is specific; i run Domoticz in a Docker container on my Synology-nas, I don't know your ip-adres and port, (could be as simple as 192.168.1.xxx:80)
SolarEdge ModbusTCP - Kaku - Synology NAS - Watermeter - ESPEasy - DS18b20
Work in progress = Life in general..
Work in progress = Life in general..