Skip to content

feat(imt_solar_si-rs485tc-2t): support lua api v3 #336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .marketplace/devices/devices.yml
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,13 @@
category: irradiance_sensors
blueprint_options:
- blueprint: irradiance_sensors/imt_solar_si-rS485tc-2t
display_name: ENP-RS485 UCM Version
display_name: ENP-RS485 UCM Version Lua API 1
description: Use Enapter ENP-RS485 to integrate IMT Solar Irradiance Sensor Si-RS485TC-2T
verification_level: verified
- blueprint: irradiance_sensors/imt_solar_si-rS485tc-2t_v3
display_name: ENP-RS485 UCM Version Lua API 3
description: Use Enapter ENP-RS485 to integrate IMT Solar Irradiance Sensor Si-RS485TC-2T
verification_level: ready_for_testing
- blueprint: irradiance_sensors/imt_solar_si-rS485tc-2t_arrakis_mk4
display_name: Arrakis MK4 IPC Version
description: Use Enapter Gateway on Arrakis MK4 IPC to integrate IMT Solar Irradiance Sensor Si-RS485TC-2T
Expand Down
16 changes: 16 additions & 0 deletions irradiance_sensors/imt_solar_si-rS485tc-2t_v3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# IMT Solar Si-RS485TC-2T

This [Enapter Device Blueprint](https://go.enapter.com/marketplace-readme) integrates **IMT Solar Si-RS485TC-2T** - irradiance sensor with [ModBus RTU](https://go.enapter.com/developers-enapter-modbus) over [RS-485 communication interface](https://go.enapter.com/developers-enapter-rs485).

## Connect to Enapter

- Sign up to the Enapter Cloud using the [Web](https://cloud.enapter.com/) or mobile app ([iOS](https://apps.apple.com/app/id1388329910), [Android](https://play.google.com/store/apps/details?id=com.enapter&hl=en)).
- Use the [Enapter ENP-RS485](https://go.enapter.com/handbook-enp-rs485) module for physical connection. See [connection instructions](https://go.enapter.com/handbook-enp-rs485-conn) in the module manual.
- [Add ENP-RS485 to your site](https://go.enapter.com/handbook-mobile-app) using the mobile app.
- [Configure your Enapter module](https://go.enapter.com/developers-set-hw-config).
- [Create a new Lua device](https://go.enapter.com/developers-provision-lua-device) using this blueprint. You can also [assign the blueprint](https://go.enapter.com/developers-assign-blueprint) to the existing Enapter UCM

## References

- [IMT Solar Si Series data sheet](https://go.enapter.com/imt-solar-si-datasheet)
- [Description MODBUS protocol for IMT Solar Si-RS485 sensors](https://go.enapter.com/imt-solar-si-modbus)
101 changes: 101 additions & 0 deletions irradiance_sensors/imt_solar_si-rS485tc-2t_v3/manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
blueprint_spec: device/3.0

display_name: IMT Solar Irradiance Sensor Si-RS485TC-2T
description: Irradiance sensor with ModBus RTU
icon: enapter-solar-panel
license: MIT
author: enapter
contributors:
- anataty
support:
url: https://go.enapter.com/enapter-blueprint-support
email: support@enapter.com

implements:
- lib.energy.pv.solar_irradiance
- lib.energy.pv.ambient_temperature

runtime:
type: lua
requirements:
- lua_api_ver_3
- modbus
options:
dir: src

configuration:
connection:
display_name: Connection
description: Modbus connection options
access_level: owner
parameters:
address:
display_name: Modbus Address
description: Device address in range 1-247
type: integer
required: true
default: 1
conn_str:
display_name: Connection string
description: Connection URI to the runtime device
type: string
required: true
default: port://rs485

properties:
vendor:
display_name: Vendor
type: string
model:
display_name: Model
type: string

telemetry:
status:
display_name: Status
type: string
enum:
- ok
- error
- modbus_error
solar_irradiance:
display_name: Solar Irradiance
type: float
unit: W/m2
module_temperature:
display_name: Module Temperature
type: float
unit: Cel
ambient_temperature:
display_name: Ambient Temperature
type: float
unit: Cel

alerts:
not_configured:
display_name: Not configured
severity: info
troubleshooting:
- Ensure that the configuration is set.
cannot_connect:
display_name: Cannot dial Modbus connection
severity: error
troubleshooting:
- Double check the physical connection.
- Ensure that Modbus address is the same as in your irradiance sensor.
- Ensure that the UCM's hardware configuration matches your irradiance sensor's communication parameters.
modbus_error:
display_name: Modbus error
severity: error
description: >
Check the device logs for specific error details and verify your connection settings.

.cloud:
category: sensors
mobile_main_chart: solar_irradiance
mobile_telemetry:
- solar_irradiance
- module_temperature
mobile_charts:
- solar_irradiance
- module_temperature
104 changes: 104 additions & 0 deletions irradiance_sensors/imt_solar_si-rS485tc-2t_v3/src/main.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
local conn = nil
local conn_cfg = nil

function main()
reconnect()
configuration.after_write('connection', function()
conn = nil
conn_cfg = nil
end)
scheduler.add(1000, reconnect)
scheduler.add(30000, send_properties)
scheduler.add(1000, send_telemetry)
end

function send_properties()
enapter.send_properties({ vendor = 'IMT Solar', model = 'Si-RS485TC-2T' })
end

function reconnect()
if conn then
return
end

local configured = configuration.is_all_required_set('connection')
if not configured then
return
end

local cfg, err = configuration.read('connection')
if err ~= nil then
enapter.log('read configuration: ' .. err, 'error')
return
end

conn_cfg = cfg
local client, err = modbus.new(conn_cfg)
if err ~= nil then
enapter.log('connect: ' .. err, 'error')
return
end

conn = client
end

function send_telemetry()
if not conn_cfg then
enapter.send_telemetry({ status = 'ok', alerts = { 'not_configured' } })
return
end
if not conn then
enapter.send_telemetry({ status = 'error', alerts = { 'cannot_connect' } })
return
end

local telemetry = {}

local data, err = conn:read({ { type = 'inputs', addr = conn_cfg.address, reg = 0, count = 1, timeout = 1000 } })
if err then
enapter.log('Read register 0 failed: ' .. err, 'error', true)
enapter.send_telemetry({ status = 'modbus_error', alerts = { 'modbus_error' } })
return
end
telemetry.solar_irradiance = apply_gain(uint16(data[1]))

local data, err = conn:read({ { type = 'inputs', addr = conn_cfg.address, reg = 7, count = 2, timeout = 1000 } })
if err then
enapter.log('Read registers 7-8 failed: ' .. err, 'error', true)
enapter.send_telemetry({ status = 'modbus_error', alerts = { 'modbus_error' } })
return
end

telemetry.module_temperature = apply_gain(int16(data[1]))
telemetry.ambient_temperature = apply_gain(uint16(data[2]))
telemetry.status = 'ok'
telemetry.alerts = {}

enapter.send_telemetry(telemetry)
end

function apply_gain(value)
local gain = 0.1
if value == nil then
return
end
return value * gain
end

function uint16(register)
if #register ~= 1 then
return
end
local raw_str = string.pack('BB', register[1] & 0xFF, register[1] >> 8)
return string.unpack('I2', raw_str)
end

function int16(register)
if #register ~= 1 then
return
end
local raw_str = string.pack('BB', register[1] & 0xFF, register[1] >> 8)
return string.unpack('i2', raw_str)
end

main()
Loading