From 18f0873faecaed716fdaca05ae10d526358494a9 Mon Sep 17 00:00:00 2001 From: Tatyana Date: Fri, 14 Jul 2023 15:15:55 +0200 Subject: [PATCH] Update http connection --- .../solarman/solarman_lua/http_connection.lua | 179 ++++-------------- 1 file changed, 36 insertions(+), 143 deletions(-) diff --git a/solar_inverters/solarman/solarman_lua/http_connection.lua b/solar_inverters/solarman/solarman_lua/http_connection.lua index ef33f97f..c83ee08c 100644 --- a/solar_inverters/solarman/solarman_lua/http_connection.lua +++ b/solar_inverters/solarman/solarman_lua/http_connection.lua @@ -1,41 +1,42 @@ -local SmappeeHTTP = {} +local SolarmanHTTP = {} local json = require('json') local net_url = require('net.url') -function SmappeeHTTP.new(username, password, client_secret, client_id, location_name) +function SolarmanHTTP.new(app_id, app_secret, username, password, device_sn) + assert(type(app_id) == 'string', 'client_id (arg #1) must be string, given: ' .. inspect(app_id)) assert( - type(username) == 'string', - 'username (arg #1) must be string, given: ' .. inspect(username) + type(app_secret) == 'string', + 'app_secret (arg #2) must be string, given: ' .. inspect(app_secret) ) assert( - type(password) == 'string', - 'password (arg #2) must be string, given: ' .. inspect(password) + type(username) == 'string', + 'username (arg #3) must be string, given: ' .. inspect(username) ) assert( - type(client_secret) == 'string', - 'client_secret (arg #3) must be string, given: ' .. inspect(client_secret) + type(password) == 'string', + 'password (arg #4) must be string, given: ' .. inspect(password) ) assert( - type(client_id) == 'string', - 'client_id (arg #4) must be string, given: ' .. inspect(client_id) + type(device_sn) == 'string', + 'password (arg #5) must be string, given: ' .. inspect(device_sn) ) - local self = setmetatable({}, { __index = SmappeeHTTP }) + local self = setmetatable({}, { __index = SolarmanHTTP }) self.username = username self.password = password - self.client_secret = client_secret - self.client_id = client_id - self.location_name = location_name + self.app_secret = app_secret + self.app_id = app_id + self.device_sn = device_sn - self.url = net_url.parse('https://app1pub.smappee.net/dev/v3') + self.url = net_url.parse('https://api.solarmanpv.com/') self.client = http.client({ timeout = 5 }) return self end -function SmappeeHTTP:process_unauthorized(request_type, headers, url, body) +function SolarmanHTTP:process_unauthorized(request_type, headers, url, body) local request = http.request(request_type, url, body) if headers ~= nil then @@ -55,7 +56,7 @@ function SmappeeHTTP:process_unauthorized(request_type, headers, url, body) end end -function SmappeeHTTP:process_authorized(request_type, url, body) +function SolarmanHTTP:process_authorized(request_type, url, body) local request = http.request(request_type, url, body) request:set_header('Authorization', 'Bearer ' .. self.access_token) @@ -72,19 +73,20 @@ function SmappeeHTTP:process_authorized(request_type, url, body) end end -function SmappeeHTTP:set_token() +function SolarmanHTTP:set_token() local body = { - grant_type = 'password', - client_id = self.client_id, - client_secret = self.client_secret, + appSecret = self.appSecret, username = self.username, password = self.password, } + local url = self.url / 'token' + url:setQuery({ appId = self.app_id }) + local headers = {} - headers['Content-Type'] = 'application/x-www-form-urlencoded' + headers['Content-Type'] = 'application/json' - local response, err = self:process_unauthorized('POST', headers, self.url .. 'oauth2/token', body) + local response, err = self:process_unauthorized('POST', headers, url, body) if err then return 'set_token failed: ' .. tostring(err) end @@ -102,137 +104,28 @@ function SmappeeHTTP:set_token() end end -function SmappeeHTTP:refresh_token() +function SolarmanHTTP:get_realtime_data() + local url = self.url / 'device/v1.0/currentData' local body = { - grant_type = 'refresh_token', - client_id = self.client_id, - client_secret = self.client_secret, - refresh_token = self.new_token, + deviceSn = self.device_sn, } - local headers = {} - headers['Content-Type'] = 'application/x-www-form-urlencoded' - - local response, err = self:process_unauthorized('POST', headers, self.url .. 'oauth2/token', body) - if err then - return 'resfresh_token failed: ' .. tostring(err) - end - - if response ~= nil then - self.access_token = response['access_token'] - self.new_token = response['refresh_token'] - if response['expires_in'] == nil then - return 'no_expire_time' - else - self.expires = response['expires_in'] + os.time() - end - else - return 'no_refresh_tokens_data' - end -end - -function SmappeeHTTP:set_service_locations() - local response, err = self:process_authorized('GET', self.url .. 'servicelocation') - if err then - return 'set_service_locations failed: ' .. tostring(err) - end - - if response ~= nil then - self.service_locations = response['serviceLocations'] - else - return 'no_data' - end -end - -function SmappeeHTTP:set_service_location_id() - local err = self:set_service_locations() - if err == nil then - if type(self.service_locations) == 'table' then - for _, location in ipairs(self.service_locations) do - for k, v in pairs(location) do - if k == 'name' and v == self.location_name then - self.service_location_id = location['serviceLocationId'] - end - end - end - if not self.service_location_id then - return 'no_service_location_id' - end - else - return 'service_locations_invalid_type' - end - else - return tostring(err) - end -end - -function SmappeeHTTP:set_metering_configuration() - local response, err = self:process_authorized( - 'GET', - self.url .. 'servicelocation/' .. self.service_location_id .. '/meteringconfiguration' - ) - if err then - return 'set_metering_configuration failed: ' .. tostring(err) - end - - if response ~= nil then - local inputs = {} - - for i, input in ipairs(response['measurements']) do - if not inputs[i] then - inputs[i] = {} - end - inputs[i]['name'] = input['name'] - for _, val in ipairs(input['channels']) do - if not inputs[i]['indexes'] then - inputs[i]['indexes'] = {} - end - inputs[i]['indexes'][val['phase']] = val['consumptionIndex'] - end - end - - self.inputs = inputs - else - return 'no_metering_data' - end -end - -function SmappeeHTTP:get_electricity_consumption(from, to) - local url = self.url / 'servicelocation' / self.service_location_id / 'consumption' - url:setQuery({ aggregation = 1, from = from, to = to }) - - local response, err = self:process_authorized('GET', url) + local response, err = self:process_authorized('POST', url, body) if err then - return nil, 'get_electricity_consumption failed: ' .. tostring(err) - end - - local err = self:set_metering_configuration() - if err ~= nil then - return nil, err + return nil, 'get_realtime_data failed: ' .. tostring(err) end local telemetry = {} if response ~= nil then - if response['serviceLocationId'] == self.service_location_id then - local data = response['consumptions'][1] - if data ~= nil then - telemetry['voltage1'] = data['lineVoltages'][1] - telemetry['voltage2'] = data['lineVoltages'][2] - telemetry['voltage3'] = data['lineVoltages'][3] - telemetry['consumption_power'] = data['consumption'] - - for i, input in ipairs(self.inputs) do - for phase, index in pairs(input['indexes']) do - telemetry['current' .. i .. '_' .. phase] = data['current'][index + 1] - telemetry['active' .. i .. '_' .. phase] = data['active'][index + 1] - end - end - telemetry['status'] = 'ok' + if response['dataList'] ~= nil then + for _, metric in response['dataList'] do + telemetry[metric.key] = metric.value end + telemetry['status'] = 'ok' else telemetry['status'] = 'warning' - telemetry['alerts'] = { 'invalid_service_location_id' } + telemetry['alerts'] = { 'no_data' } end end telemetry['status'] = 'warning' @@ -241,4 +134,4 @@ function SmappeeHTTP:get_electricity_consumption(from, to) return telemetry, nil end -return SmappeeHTTP +return SolarmanHTTP