03.03.2026, 06:45
Finally i got it working for Plugwise Smile V3
Code:
require('socket')
local mime = require('mime')
-- 1. CONFIGURATION: Mapping IDs to your Group Addresses
local mapping = {
-- Cumulative Totals (Wh -> kWh)
['986c55ddad604a018b5d216dc8aa37a1'] = { peak = '26/1/1', offpeak = '26/1/2' },
['f4fdea65cc874c5c8297193a6544dff0'] = { peak = '26/1/3', offpeak = '26/1/4' },
-- Instant Power Consumption (Watts)
['e90c4162ce094563bda979d3fe74eb58'] = '26/1/11', -- L1
['0ec9018894934dd6a4ef7e558838b844'] = '26/1/12', -- L2
['3fd23238e9e04dcc8fbf379ff9b24fc4'] = '26/1/13', -- L3
-- Instant Power Production (Watts)
['eb087cabceda45a9abb87103195e0049'] = '26/1/21', -- L1
['1f1a0baab8364a4f860084b075be4659'] = '26/1/22', -- L2
['4061da769ee8422c86e29634ed6f8a61'] = '26/1/23', -- L3
-- Voltages (Volts)
['a691532ba05442bc8d9fc0da21d1e674'] = '26/1/31', -- L1
['89a129b2e69945ee850b3e939235ed36'] = '26/1/32', -- L2
['fb657c3e3e3041d6b91e457781055c51'] = '26/1/33', -- L3
-- NEW: Current (Amperes)
['64c73a3ef3f04daf865e84d81168020c'] = '26/1/41', -- L1 Current
['b6bfa6f7685343da867a34dbd5e1bd03'] = '26/1/42', -- L2 Current
['4061da769ee8422c86e29634ed6f8a61'] = '26/1/43', -- L3 Current
}
-- 2. NETWORK SETTINGS
local ip = '192.168.1.1'
local auth = mime.b64('smile:********')
-- 3. FETCH DATA VIA TCP SOCKET
local client = socket.tcp()
client:settimeout(15)
local res, err = client:connect(ip, 80)
if res then
client:send("GET /core/domain_objects HTTP/1.1\r\n")
client:send("Host: " .. ip .. "\r\n")
client:send("Authorization: Basic " .. auth .. "\r\n")
client:send("Connection: close\r\n\r\n")
local response = {}
while true do
local chunk, status, partial = client:receive(2048)
local data = chunk or partial
if data then table.insert(response, data) end
if status == "closed" then break end
end
client:close()
local full_data = table.concat(response)
-- 4. PARSE AND WRITE
if #full_data > 1000 then
for log_id, content in full_data:gmatch('id=["\'](.-)["\'].->(.-)</%w+_log>') do
local target = mapping[log_id]
if target then
if type(target) == 'table' then
-- Dual Tariff Parsing
local offpeak = content:match('tariff=["\']nl_offpeak["\'].->(.-)</measurement>')
local peak = content:match('tariff=["\']nl_peak["\'].->(.-)</measurement>')
if offpeak then grp.checkupdate(target.offpeak, tonumber(offpeak) / 1000) end
if peak then grp.checkupdate(target.peak, tonumber(peak) / 1000) end
else
-- Single Measurement Parsing (Watts, Volts, Amps)
local val_str = content:match('<measurement.->(.-)</measurement>')
if val_str then
local n_val = tonumber(val_str)
grp.checkupdate(target, n_val)
-- log('Update ' .. target .. ' = ' .. n_val)
end
end
end
end
log('P1: Full Update Successful (' .. #full_data .. ' bytes)')
end
else
log('P1: Connection failed: ' .. tostring(err))
end