Skip to content

[shelly] Add support for LoRa Add-On - #19006

Open
markus7017 wants to merge 17 commits into
openhab:mainfrom
markus7017:shelly_lora
Open

[shelly] Add support for LoRa Add-On#19006
markus7017 wants to merge 17 commits into
openhab:mainfrom
markus7017:shelly_lora

Conversation

@markus7017

@markus7017 markus7017 commented Jul 21, 2025

Copy link
Copy Markdown
Contributor

Description

Feature — Adds support for the Shelly LoRa Add-On, enabling LoRa datagram send/receive on compatible devices.

Two hardware variants are supported: the plug-in Plus/Gen3/Gen4 LoRa Add-On and the DIN-rail Pro LoRa Add-On.

Supported hardware:

  • Shelly LoRa Add-On (plug-in, Gen3/Gen4): Plus 1, Plus 1PM, Plus 2PM, Plus Shutter, Plus EM, Dimmer 0/1-10V PM Gen3/Gen4. Regions: EU868, US915, BR915-928. Requires firmware ≥ 1.6.

  • Shelly Pro LoRa Add-On (DIN-rail, Pro series): Pro 1, Pro 1PM, Pro 2, Pro 2PM, Pro 3EM, Pro EM-50, Pro Dimmer 1PM, Pro Dimmer 2PM, Pro Dimmer 0/1-10V PM. EU868 only. Requires firmware ≥ 2.0.

  • Feature: The add-on is detected automatically when the Thing initializes — no configuration option needed to enable it.

  • Feature: A lora channel group is created automatically once the add-on is detected.

  • Feature: Send text or raw BASE64 datagrams via the dataTx/dataTxRaw channels; TX byte count and send errors are tracked.

  • Feature: When the add-on's own RX path is enabled, received datagrams are exposed via dataRx/dataRxRaw, along with signal quality (rssi, snr) of the last received packet.

  • Feature: Cumulative on-air time is tracked via the airtime channel.

  • Feature: A new LORA_RECEIVED alarm trigger event fires whenever a datagram is received, for use in rules.

  • Feature: The add-on's firmware version is reported as a thing property.

Channel group lora:

Group Channel Type Description
lora dataRx String Received datagram as UTF-8 text (RX only)
lora dataRxRaw String Received datagram, BASE64 raw (RX only)
lora bytesRx Number:DataAmount Total bytes received (RX only)
lora dataTx String Send UTF-8 text (binding encodes to BASE64)
lora dataTxRaw String Send BASE64-encoded datagram directly
lora bytesTx Number:DataAmount Total bytes sent
lora errorsTx Number Send failures
lora rssi Number:Dimensionless RSSI of last received packet (dBm) (RX only)
lora snr Number:Dimensionless SNR of last received packet (dB) (RX only)
lora airtime Number:Time Cumulative on-air time (ms)

References:

Testing

Manual verification:

  • Attach a Shelly LoRa Add-on (or Pro LoRa Add-on) to a supported device and power it on.
  • Confirm the lora channel group appears automatically, with no configuration required.
  • Send a text message via dataTx and confirm it is received by another LoRa node.
  • If RX is enabled in the add-on's own configuration, send a datagram to the device and confirm dataRx/dataRxRaw/rssi/snr update and the LORA_RECEIVED alarm trigger fires.
  • Confirm the add-on firmware version appears as a thing property.

Acceptance criteria

  • Implementation done
  • Documentation is up-to-date
  • Verified by Community

Closing

Backport assessment

New feature only — no bug fixes. Not a candidate for backport.

@markus7017 markus7017 self-assigned this Jul 21, 2025
@markus7017 markus7017 added enhancement An enhancement or new feature for an existing add-on work in progress A PR that is not yet ready to be merged labels Jul 21, 2025
@wborn
wborn requested a review from Copilot July 26, 2025 13:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for Shelly LoRa Add-On functionality, enabling communication with LoRa WAN networks through compatible Gen3+ Shelly devices. The implementation includes event handling for received LoRa datagrams and provides channels for transmitting and monitoring LoRa network statistics.

  • Integration of LoRa Add-On detection and channel creation
  • JavaScript event handler for LoRa data reception and decoding
  • Configuration option to enable/disable LoRa support

Reviewed Changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
oh-lora.js JavaScript event handler for receiving and processing LoRa datagrams
shellyGen2_relay.xml Channel group and channel type definitions for LoRa functionality
shelly.properties Internationalization strings for LoRa configuration and channels
config2.xml Configuration parameters to enable LoRa support
ShellyChannelDefinitions.java Channel definitions and creation logic for LoRa channels
ShellyComponents.java Component update methods for LoRa status handling
ShellyThingConfiguration.java Configuration property for LoRa enablement
Shelly2ApiRpc.java RPC API integration for LoRa script installation and event handling
Shelly2ApiJsonDTO.java Data transfer objects for LoRa configuration and status
Shelly2ApiClient.java Client-side LoRa status update implementation
Shelly1ApiJsonDTO.java LoRa detection flags in device settings
ShellyBindingConstants.java LoRa channel and group constants
README.md Documentation for LoRa Add-On functionality

Comment thread bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/config2.xml Outdated
Comment thread bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/config2.xml Outdated
Comment thread bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/config2.xml Outdated
Comment thread bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/config2.xml Outdated
Comment thread bundles/org.openhab.binding.shelly/src/main/resources/scripts/oh-lora.js Outdated
Comment thread bundles/org.openhab.binding.shelly/README.md Outdated
@markus7017
markus7017 force-pushed the shelly_lora branch 3 times, most recently from d8f8bce to f67a5d4 Compare August 1, 2025 20:59
@markus7017 markus7017 added awaiting other PR Depends on another PR and removed awaiting other PR Depends on another PR labels Aug 1, 2025
@markus7017
markus7017 force-pushed the shelly_lora branch 2 times, most recently from 82ca7d3 to a37636f Compare August 14, 2025 20:15
@markus7017
markus7017 force-pushed the shelly_lora branch 3 times, most recently from 440458d to d187ad6 Compare August 23, 2025 15:41
@markus7017 markus7017 added awaiting other PR Depends on another PR and removed work in progress A PR that is not yet ready to be merged labels Aug 23, 2025
@markus7017
markus7017 requested a review from jlaur August 23, 2025 19:04
@lolodomo

Copy link
Copy Markdown
Contributor

Waiting PR was merged.
You have conflicts to resolve.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread bundles/org.openhab.binding.shelly/README.md Outdated

@lsiepel lsiepel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the code, i found some comments and questions.

More generally, I’m wondering about the usefulness and design of the exposed channels.

There are several “statistics” style channels (signal, RX/TX errors, etc.). Do we expect users to build rules/dashboards around these? If yes, it might be worth documenting the intended use. If not, we might consider limiting what we expose by default (or grouping them clearly as “diagnostics”).

There are also two channels for payload data that appear duplicated: one as raw(?) and another as Base64. Can you clarify why both are needed, and when a user would choose one over the other?

From what I can tell, this currently behaves primarily like router/bridge functionality: it takes LoRa messages and forwards them onto the openHAB event bus. That can be useful, but it’d be good to make the intent explicit (and confirm whether we’re aiming for:
a generic “LoRa message forwarder”, or
device-specific interpretation + semantically meaningful channels).

I'd like to ask @jlaur to also have a brief look into this.

Comment thread bundles/org.openhab.binding.shelly/README.md Outdated
@markus7017 markus7017 added the work in progress A PR that is not yet ready to be merged label Jan 22, 2026
@markus7017
markus7017 force-pushed the shelly_lora branch 2 times, most recently from fa6664e to e0ce401 Compare June 14, 2026 22:40
@lsiepel

lsiepel commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Did you push the conflict resolving? No change recorded.

@lsiepel

lsiepel commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Almost there still a conflict

@markus7017

Copy link
Copy Markdown
Contributor Author

@lsiepel changes applied

@lsiepel

lsiepel commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

New conflicts introduced

@openhab-bot

Copy link
Copy Markdown
Collaborator

This pull request has been mentioned on openHAB Community. There might be relevant details there:

https://community.openhab.org/t/shelly-beta-with-plus-pro-mini-and-blu-support/139554/1

@markus7017

Copy link
Copy Markdown
Contributor Author

@lsiepel Would you like to trigger a Copilot/Codex?

@lsiepel lsiepel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There you go. fully created by codex, only scanned the issues so please double check if they are valid and if the proposal makes sense.

Supports the Shelly LoRa Add-On (Gen3/Gen4) and Shelly Pro LoRa Add-On:
sending and receiving transparent LoRa datagrams via the new lora
channel group. RX events arrive as NotifyEvent; payloads are Base64 on
the wire, the binding offers decoded text and raw Base64 channels for
both directions. The wall dimmer does not support add-ons and is
excluded.

Signed-off-by: Markus Michels <markus7017@gmail.com>
- Fix loraSignal channel description (was wrong "0-4" scale; actual RSSI is dBm)
- Fix loraSNR channel category: Flow -> QualityOfService
- Add band_plan field to Shelly2DeviceConfigLora (LoRa.GetConfig response)
- Add errors and flags fields to Shelly2DeviceStatusLora (LoRa.GetStatus response)
- Extract duplicate Base64 padding fix to ShellyUtils.fixBase64Padding()
- Use fixBase64Padding() in RX event handler (Shelly2ApiRpc) and TX channel (ShellyRelayHandler)
- Change loraSendData() to throw ShellyApiException instead of IllegalArgumentException

Signed-off-by: Markus Michels <markus7017@gmail.com>
- ShellyLoraBase64Test: delegate decode() helper to ShellyUtils.fixBase64Padding()
- ShellyLoraBase64Test: add fixBase64Padding parametrized tests (len%4 == 0/2/3)
- ShellyLoraBase64Test: add rem==1 guard test (invalid Base64 must not throw in util)
- Shelly2GetDeviceProfileTest: add band_plan Gson round-trip test

Signed-off-by: Markus Michels <markus7017@gmail.com>
Add LoRa channel group documentation:
- LORA_RECEIVED trigger event in the Alarms/Events table
- LoRa Add-On channel group section with supported devices, configuration,
  and channel table (all 10 channels: dataRx/Tx, raw variants, byte counts,
  errorsTx, SNR, RSSI, airtime)

Signed-off-by: Markus Michels <markus7017@gmail.com>
…a option

The lora100 component is only present in the device GetConfig when the
add-on is physically installed, so the extra thing config option was
redundant. Detection now follows the same auto-detect pattern as the
sensor add-on.

Signed-off-by: Markus Michels <markus7017@gmail.com>
…hannel

The device reports the add-on firmware version asynchronously, so at
channel-creation time the value is always empty and the channel was
never created. A version string is device metadata, not a state to
track — the value now goes to the addonFirmware thing property, updated
whenever the device delivers it.

Signed-off-by: Markus Michels <markus7017@gmail.com>
Adds Measurement/Status/Control/Duration tags to the LoRa channel
types, aligns the airtime description between XML and i18n, and updates
the README channel table to the UoM item types (Number:DataAmount,
Number:Time).

Signed-off-by: Markus Michels <markus7017@gmail.com>
- Send the padded Base64 string to the device (LoRa.SendBytes requires
  valid Base64); user input without padding was forwarded unmodified
- Ignore empty send commands on both TX channels
- Warn instead of debug-log when a raw payload is not valid Base64
- Tighten the NotifyEvent JSON patch to the lora component marker so
  unrelated events containing "lora:" in a value are not rewritten
- Remove unused ShellyNotifyLoraEvent DTO
- Test method names follow the camelCase convention

Signed-off-by: Markus Michels <markus7017@gmail.com>
…pdates

Covers flag-driven channel creation with an empty device status (the
add-on reports no LoRa data at initialization time), the loraRxEnabled
gating of the Rx channels, counter channel updates, and the async
addonFirmware property handling.

Signed-off-by: Markus Michels <markus7017@gmail.com>
…isabled

RSSI/SNR are only updated on the RX event path, which requires
loraRxEnabled. They were previously created unconditionally, leaving
them permanently UNDEF on RX-disabled devices.

Signed-off-by: Markus Michels <markus7017@gmail.com>
The README documents LORA_RECEIVED as a valid alarm trigger event, but
it was missing from the alarmTrigger channel-type's options, hurting
UI/rule-editor discoverability.

Signed-off-by: Markus Michels <markus7017@gmail.com>
Merge discoveryLoraRxEnabledFlagTrue/False into one parameterized
test and drop a dangling decorative comment.

Signed-off-by: Markus Michels <markus7017@gmail.com>
…ATA case

Signed-off-by: Markus Michels <markus7017@gmail.com>
… in onMessage

Signed-off-by: Markus Michels <markus7017@gmail.com>
The RPC layer only recognized the legacy flattened "lora_received" event
and had no DTO field for the documented "info" object, so on current
firmware the "lora" event fell through unhandled: RX channels and the
trigger never updated. The forced string-rename workaround in
Shelly2RpcSocket is no longer needed once the DTO models "info" directly.

Also force the RX trigger on every datagram: postEvent's de-dup was
swallowing all but the first of a fast burst since the alarm value never
changes between packets. Introduce a dedicated ALARM_TYPE_LORA_RECEIVED
constant so the forced trigger value doesn't accidentally couple to the
JSON event name constant.

RSSI and SNR are now published as unit-aware quantities (Number:Power /
Number:Dimensionless with dBm/dB) instead of plain numbers, matching how
other bindings model signal quality.

Signed-off-by: Markus Michels <markus7017@gmail.com>
NotifyStatus is a delta: fields the device didn't change are omitted and
deserialize as null. updateLoraStatus() applied every field
unconditionally, so an update touching only one LoRa property overwrote
the other channels with UNDEF (or 0 for txErrors), clobbering valid
state. Only update a channel when its field is present in the delta.

Signed-off-by: Markus Michels <markus7017@gmail.com>
The Add-On's air_time_hr_ms is not cumulative; Shelly defines it as
transmission time during the last 60 minutes. Update the channel-type,
i18n and README descriptions to match, so the UI doesn't imply
lifetime/persisted semantics.

Signed-off-by: Markus Michels <markus7017@gmail.com>
@markus7017 markus7017 removed the work in progress A PR that is not yet ready to be merged label Aug 22, 2026
@markus7017

Copy link
Copy Markdown
Contributor Author

@lsiepel changes applied

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

additional testing preferred The change works for the pull request author. A test from someone else is preferred though. enhancement An enhancement or new feature for an existing add-on

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants