Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
a1bd29c
Move JK200-MBS into JKESS/JK200-MBS namespace
Feb 27, 2026
a9b4488
Add LinkedGo ST802 thermostat Modbus RTU BMS client
Feb 27, 2026
911ba85
Add Shelly script deploy and monitor skill document
Feb 27, 2026
ef17912
Update CHANGELOG for ST802 client, deploy skill, and JKESS rename
Feb 27, 2026
9ae9669
Merge feature/linkedgo-st802-bms-client into dev
Feb 27, 2026
9af4325
Merge dev into main
Feb 27, 2026
0843130
Sync manifest and index after JKESS rename
Feb 27, 2026
cd4f1eb
Back-merge manifest sync from main into dev
Feb 27, 2026
a1e2973
Move ST802 script into ST802/ subdirectory and update CHANGELOG path
Feb 27, 2026
28ee6cc
Merge dev into main
Feb 27, 2026
2dc1960
Mark ST802 BMS client as production; add poll flags and @link
Feb 27, 2026
6d4655a
Merge feature/st802-production-status into dev
Feb 27, 2026
a2cfba0
Merge dev into main
Feb 27, 2026
da439a2
Add modbus-device-template skill file
Feb 28, 2026
f4a2c91
refactor(Deye): expand ENTITIES to full template structure
Feb 28, 2026
5232ba6
refactor(Deye VC): expand ENTITIES to full template structure
Feb 28, 2026
6b4b301
refactor(JK200): add ENTITIES metadata layer alongside block-read REG…
Feb 28, 2026
99cff9e
refactor(MB308V): replace MB308V object with typed ENTITIES array
Feb 28, 2026
66d61a6
refactor(ST802): replace REG address map with ENTITIES + derived REG
Feb 28, 2026
e43ab2d
Merge feature/modbus-entities-template-refactor into dev
Feb 28, 2026
9005694
rename(Deye): simplify CLI script filename to deye.shelly.js
Mar 1, 2026
f4ea848
rename(Deye VC): simplify VC script filename to deye_vc.shelly.js
Mar 1, 2026
797ae0b
rename(JK200): simplify CLI script filename to jk200.shelly.js
Mar 1, 2026
7a1e6db
feat(JK200 VC): add Virtual Component variant of JK200 BMS script
Mar 1, 2026
38f0826
feat(MB308V VC): add Virtual Component demo for CWT-MB308V IO module
Mar 1, 2026
65379b7
feat(ST802 VC): add Virtual Component variant of ST802 thermostat script
Mar 1, 2026
4b0bdd6
docs(skills): add modbus-vc-deploy skill for VC provisioning workflow
Mar 1, 2026
9e7fade
Merge feature/modbus-vc-examples into dev
Mar 1, 2026
fd64f35
docs(skills): add rs485-for-the-pill skill file
Mar 1, 2026
19069f7
docs(modbus-rtu): update wiring to The Pill IO1/IO2/IO3 pin names
Mar 1, 2026
516c633
docs(Deye): update wiring to The Pill IO1/IO2/IO3 pin names
Mar 1, 2026
1434f90
docs(JK200): update wiring to The Pill IO1/IO2/IO3 pin names
Mar 1, 2026
1dae5da
docs(MB308V): update wiring to The Pill IO1/IO2/IO3 pin names
Mar 1, 2026
b3f68ba
docs(ST802): update wiring to The Pill IO1/IO2/IO3 pin names
Mar 1, 2026
40e3bcc
Merge feature/rs485-io3-direction-control into dev
Mar 1, 2026
a184701
Add LinkedGo R290 and MODBUS README stories
Mar 1, 2026
9908be7
Merge feature/modbus-readme-rs485-story-persona into dev
Mar 1, 2026
42c2877
Merge dev into main
Mar 1, 2026
c0a5cc1
Add manifest verify tools skill
Mar 1, 2026
53f53db
Refactor SDS011 VC script layout
Mar 1, 2026
5f8768f
Merge feature/sds011-vc-cycle-cleanup into dev
Mar 1, 2026
6791e32
Add Yahoo finance integration docs
Mar 1, 2026
a1f8bfe
Merge feature/finance-yahoo-readme-headers into dev
Mar 1, 2026
00b48b3
Add git workflow cleanup skill
Mar 1, 2026
685c956
Merge feature/git-skill-commit-cleanup into dev
Mar 1, 2026
4ca3220
Standardize BLE open windows script
Mar 1, 2026
b0f0298
Merge feature/ble-open-windows-standardize into dev
Mar 1, 2026
0bebc17
Add JS-to-Shelly skill guide
Mar 1, 2026
ea5c44e
Merge feature/js-to-shelly-standardize-skill into dev
Mar 1, 2026
a0d11ee
Add MODBUS-RTU HTTP Bridge for The Pill
Mar 1, 2026
dd2d974
Merge feature/modbus-http-bridge into dev
Mar 1, 2026
4b24405
Merge dev into main
Mar 1, 2026
e01fe37
Promote MODBUS scripts and sync docs
Mar 2, 2026
803f16e
Merge feature/modbus-production-and-doc-sync into dev
Mar 2, 2026
bab61ea
Merge dev into main
Mar 2, 2026
bf9e3dc
Merge branch 'ALLTERCO:main' into main
orlin369 Mar 2, 2026
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
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,33 @@

All notable changes to this project will be documented in this file.

## 2026-03
- Add screenshot sections with descriptive captions to Deye, JK200, and ST802 MODBUS README files
- Promote `the_pill/MODBUS/Deye/deye.shelly.js` to production and fix its header `@link` path
- Promote `the_pill/MODBUS/Deye/deye_vc.shelly.js` to production and fix its header `@link` path
- Promote `the_pill/MODBUS/LinkedGo/ST802/st802_bms.shelly.js` to production and update its header `@link` to the ALLTERCO repository path
- Promote `the_pill/MODBUS/LinkedGo/ST802/st802_bms_vc.shelly.js` to production and update its header `@link` to the ALLTERCO repository path
- Promote `the_pill/MODBUS/JKESS/JK200-MBS/jk200.shelly.js` to production and fix its header `@link` path
- Promote `the_pill/MODBUS/JKESS/JK200-MBS/jk200_vc.shelly.js` to production and fix its header `@link` path
- Change JK200 VC `Pack Current` unit from `mA` to `A` and scale value conversion in `jk200_vc.shelly.js`; update `skills/modbus-vc-deploy.md` JK200 VC table and creation example
- Change JK200 VC `Pack Power` unit from `mW` to `W` and scale value conversion in `jk200_vc.shelly.js`; update `skills/modbus-vc-deploy.md` JK200 VC table and creation example
- Change JK200 VC `Pack Voltage` unit from `mV` to `V` and scale value conversion in `jk200_vc.shelly.js`; update `skills/modbus-vc-deploy.md` VC creation table accordingly
- Update `skills/modbus-vc-deploy.md` to require including all created VCs in `Group.Set` membership so grouped components are visible in Shelly UI
- Add `skills/js-to-shelly-standardize.md` for converting non-standard `.js` files into repository-compliant `.shelly.js` scripts with required headers and doc updates
- Standardize BLE open windows script by renaming `ble/open_windows.js` to `ble/ble-open-windows.shelly.js`, adding standard headers, and aligning code style/structure
- Add `skills/git-commit-merge-cleanup.md` documenting the team Git flow and required local/remote `feature/*` branch cleanup after merges
- Add `http-integrations/finance-yahoo/README.md` with Problem (The Story) and Persona sections for the Yahoo Finance stock monitor example
- Rename `http-integrations/finance-yahoo/stock_monitor 2.js` to `http-integrations/finance-yahoo/stock-monitor.shelly.js` to follow script naming standards
- Remove legacy SDS011 setup/UI scripts and rename `uart_lib_SDS011.js` to `the_pill/SDS011/sds011-vc-cycle.shelly.js`; add standard metadata headers and refresh SDS011 README references
- Add LinkedGo R290 A/W thermal pump MODBUS-RTU example for The Pill (`the_pill/MODBUS/LinkedGo/r290_aw_thermal_pump.shelly.js`) with FC03 polling, FC06 control helpers, and RS485 wiring notes
- Update all `the_pill/MODBUS/**/README.md` files with RS485-for-The-Pill wiring guidance plus `Problem (The Story)` and `Persona` sections; add missing README files for `JKESS`, `LinkedGo`, `LinkedGo/ST802`, and `LinkedGo/R290`
- Add skill document `skills/manifest-verify-tools.md` for strict `tools/`-driven manifest/index verification and regeneration workflow

## 2026-02
- Mark LinkedGo ST802 BMS client as production; add @link, POLL_MODE, POLL_FAN_SPEED, POLL_HUMIDITY flags
- Add LinkedGo ST802 Youth Smart Thermostat Modbus RTU BMS client (`the_pill/MODBUS/LinkedGo/ST802/st802_bms.shelly.js`) with enable-flag mechanism for 8 BMS scenarios
- Add Shelly script deploy and monitor skill document (`skills/shelly-script-deploy.md`)
- Move JK200 BMS script into JKESS/JK200-MBS namespace
- Mark YS-IRTM scripts as production; add all 6 to manifest; remove Under Development banner from README
- Add JK200 BMS MODBUS-RTU reader (`the_pill/MODBUS/JK200-MBS`) with README
- Mark Deye SG02LP1 MODBUS-RTU scripts as production; fix @link URLs; add to manifest; add README
Expand Down
22 changes: 17 additions & 5 deletions SHELLY_MJS.md
Original file line number Diff line number Diff line change
Expand Up @@ -404,18 +404,30 @@ switch-input/shelly2p-domo-coverfix.shelly.js: Shelly Plus 2PM cover fix for Dom
Simple fix for outgoing Domoticz MQTTAD command 'GoToPosition'.
Shelly firmware 0.x supported. Developed for ShellyTeacher4Domo.

the_pill/MODBUS/Deye/the_pill_mbsa_deye.shelly.js: Deye SG02LP1 MODBUS-RTU
the_pill/MODBUS/Deye/deye.shelly.js: Deye SG02LP1 MODBUS-RTU
===
MODBUS-RTU example for reading Deye SG02LP1 solar inverter parameters over UART using the MODBUS-RTU master library.
MODBUS-RTU example for reading Deye SG02LP1 solar inverter

the_pill/MODBUS/Deye/the_pill_mbsa_deye_vc.shelly.js: Deye SG02LP1 MODBUS-RTU + Virtual Components
the_pill/MODBUS/Deye/deye_vc.shelly.js: Deye SG02LP1 MODBUS-RTU + Virtual Components
===
MODBUS-RTU reader for Deye SG02LP1 solar inverter with Virtual Component updates. Reads parameters over UART (RS485) and pushes values to user-defined virtual number components.
MODBUS-RTU reader for Deye SG02LP1 solar inverter with

the_pill/MODBUS/JK200-MBS/the_pill_mbsa_jk200.shelly.js: JK200 BMS MODBUS-RTU Reader
the_pill/MODBUS/JKESS/JK200-MBS/jk200.shelly.js: JK200 BMS MODBUS-RTU Reader
===
MODBUS-RTU reader for Jikong JK-PB series BMS over RS485.

the_pill/MODBUS/JKESS/JK200-MBS/jk200_vc.shelly.js: JK200 BMS MODBUS-RTU Reader + Virtual Components
===
MODBUS-RTU reader for Jikong JK-PB series BMS over RS485 with

the_pill/MODBUS/LinkedGo/ST802/st802_bms.shelly.js: LinkedGo ST802 Thermostat - BMS Modbus RTU Client
===
Modbus RTU master that simulates BMS (Building Management System)

the_pill/MODBUS/LinkedGo/ST802/st802_bms_vc.shelly.js: LinkedGo ST802 Thermostat - BMS Modbus RTU Client + Virtual Components
===
Modbus RTU master that simulates BMS commands for the LinkedGo

the_pill/UART/uart_test.shelly.js: UART test
===
Simple UART loopback test that sends periodic messages and prints received data.
Expand Down
2 changes: 1 addition & 1 deletion ble/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ Use these examples to connect Shelly devices to nearby BLE/BLU sensors and butto
- `ble-shelly-dw.shelly.js`
- `ble-shelly-motion.shelly.js`
- `ble-shelly-scanner.shelly.js`
- `ble-open-windows.shelly.js`
- `hue-lights-control.shelly.js`
- `universal-blu-to-mqtt.shelly.js`

264 changes: 264 additions & 0 deletions ble/ble-open-windows.shelly.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
/**
* @title BLE open windows monitor
* @description Scans Shelly BLU DoorWindow advertisements, tracks open windows,
* and updates Virtual Components with aggregate open-state information.
* @status under development
* @link https://github.com/ALLTERCO/shelly-script-examples/blob/main/ble/ble-open-windows.shelly.js
*/

/**
* BLE Open Windows Monitor
*
* Watches configured BLU DoorWindow devices and publishes:
* - boolean:200 true if any configured window is open
* - number:200 count of open windows
* - text:200 last update timestamp
* - text:201 most recently opened window name (or None)
*/

// ============================================================================
// CONFIGURATION
// ============================================================================

const DEVICES = {
// Replace sample MAC addresses with your real BLU DoorWindow addresses.
'xx:xx:xx:xx:xx:01': { res: {}, name: 'Living Room Back Window', date: null },
'xx:xx:xx:xx:xx:02': { res: {}, name: 'Children Room Front Window', date: null },
};

const COMPONENT_ANY_OPEN = 'boolean:200';
const COMPONENT_OPEN_COUNT = 'number:200';
const COMPONENT_LAST_UPDATE = 'text:200';
const COMPONENT_LAST_OPEN_NAME = 'text:201';

const BTHOME_SVC_ID_STR = 'fcd2';

// ============================================================================
// HELPERS
// ============================================================================

function setValue(component, value) {
const handle = Virtual.getHandle(component);
if (handle) {
handle.setValue(value);
}
}

function getTimestamp(date) {
return date.toString().split('GMT')[0];
}

function getByteSize(type) {
if (type === uint8 || type === int8) {
return 1;
}
if (type === uint16 || type === int16) {
return 2;
}
if (type === uint24 || type === int24) {
return 3;
}
return 255;
}

// ============================================================================
// EVENT PROCESSING
// ============================================================================

function onEvent(res) {
const addr = res.addr;
const device = DEVICES[addr];
if (!device) {
return;
}

const date = new Date();
device.res = res;
device.date = date;

let isOpenWindow = false;
let openWindowsCount = 0;
let lastOpenWindowDevice = null;

for (const dev in DEVICES) {
const trackedDevice = DEVICES[dev];
if (trackedDevice.res.window === 1) {
openWindowsCount += 1;
isOpenWindow = true;
if (!lastOpenWindowDevice || lastOpenWindowDevice.date <= trackedDevice.date) {
lastOpenWindowDevice = trackedDevice;
}
}
}

setValue(COMPONENT_ANY_OPEN, isOpenWindow);
setValue(COMPONENT_OPEN_COUNT, openWindowsCount);
setValue(COMPONENT_LAST_UPDATE, getTimestamp(date));
setValue(COMPONENT_LAST_OPEN_NAME, lastOpenWindowDevice ? lastOpenWindowDevice.name : 'None');
}

function scanCB(ev, res) {
if (
ev !== BLE.Scanner.SCAN_RESULT ||
!res ||
!DEVICES[res.addr] ||
!res.service_data ||
!res.service_data[BTHOME_SVC_ID_STR]
) {
return;
}

const bthomeData = ShellyBLUParser.getData(res);
if (bthomeData) {
onEvent(bthomeData);
return;
}

print('Failed to parse BTH data:', JSON.stringify(res));
}

function startBleScan() {
const success = BLE.Scanner.Start(
{ duration_ms: BLE.Scanner.INFINITE_SCAN, active: false },
scanCB
);
print('BLE scanner running:', success !== false);
}

function init() {
const bleConfig = Shelly.getComponentConfig('ble');
if (bleConfig.enable === false) {
print('Error: BLE not enabled');
return;
}

startBleScan();
}

// ============================================================================
// BTHOME PARSER
// ============================================================================

const uint8 = 0;
const int8 = 1;
const uint16 = 2;
const int16 = 3;
const uint24 = 4;
const int24 = 5;

const BTH = [];
BTH[0x00] = { n: 'pid', t: uint8 };
BTH[0x01] = { n: 'battery', t: uint8, u: '%' };
BTH[0x02] = { n: 'temperature', t: int16, f: 0.01, u: 'tC' };
BTH[0x03] = { n: 'humidity', t: uint16, f: 0.01, u: '%' };
BTH[0x05] = { n: 'illuminance', t: uint24, f: 0.01 };
BTH[0x21] = { n: 'motion', t: uint8 };
BTH[0x2d] = { n: 'window', t: uint8 };
BTH[0x3a] = { n: 'button', t: uint8 };
BTH[0x3f] = { n: 'rotation', t: int16, f: 0.1 };

const ShellyBLUParser = {
getData: function(res) {
const result = BTHomeDecoder.unpack(res.service_data[BTHOME_SVC_ID_STR]);
if (result) {
result.addr = res.addr;
result.rssi = res.rssi;
}
return result;
},
};

const BTHomeDecoder = {
utoi: function(num, bitsz) {
const mask = 1 << (bitsz - 1);
return num & mask ? num - (1 << bitsz) : num;
},
getUInt8: function(buffer) {
return buffer.at(0);
},
getInt8: function(buffer) {
return this.utoi(this.getUInt8(buffer), 8);
},
getUInt16LE: function(buffer) {
return 0xffff & ((buffer.at(1) << 8) | buffer.at(0));
},
getInt16LE: function(buffer) {
return this.utoi(this.getUInt16LE(buffer), 16);
},
getUInt24LE: function(buffer) {
return 0x00ffffff & ((buffer.at(2) << 16) | (buffer.at(1) << 8) | buffer.at(0));
},
getInt24LE: function(buffer) {
return this.utoi(this.getUInt24LE(buffer), 24);
},
getBufValue: function(type, buffer) {
if (buffer.length < getByteSize(type)) {
return null;
}

let res = null;
if (type === uint8) {
res = this.getUInt8(buffer);
}
if (type === int8) {
res = this.getInt8(buffer);
}
if (type === uint16) {
res = this.getUInt16LE(buffer);
}
if (type === int16) {
res = this.getInt16LE(buffer);
}
if (type === uint24) {
res = this.getUInt24LE(buffer);
}
if (type === int24) {
res = this.getInt24LE(buffer);
}
return res;
},
unpack: function(buffer) {
if (typeof buffer !== 'string' || buffer.length === 0) {
return null;
}

const result = {};
const dib = buffer.at(0);
result.encryption = dib & 0x1 ? true : false;
result.BTHome_version = dib >> 5;

// Encrypted data is not handled.
if (result.BTHome_version !== 2 || result.encryption) {
return null;
}

buffer = buffer.slice(1);
while (buffer.length > 0) {
const bth = BTH[buffer.at(0)];
if (typeof bth === 'undefined') {
return null;
}

buffer = buffer.slice(1);
let value = this.getBufValue(bth.t, buffer);
if (value === null) {
return null;
}

if (typeof bth.f !== 'undefined') {
value = value * bth.f;
}

result[bth.n] = value;
buffer = buffer.slice(getByteSize(bth.t));
}

return result;
},
};

// ============================================================================
// STARTUP
// ============================================================================

init();
25 changes: 20 additions & 5 deletions examples-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -459,20 +459,35 @@
"description": "Simple fix for outgoing Domoticz MQTTAD command 'GoToPosition'.\n Shelly firmware 0.x supported. Developed for ShellyTeacher4Domo."
},
{
"fname": "the_pill/MODBUS/Deye/the_pill_mbsa_deye.shelly.js",
"fname": "the_pill/MODBUS/Deye/deye.shelly.js",
"title": "Deye SG02LP1 MODBUS-RTU",
"description": "MODBUS-RTU example for reading Deye SG02LP1 solar inverter parameters over UART using the MODBUS-RTU master library."
"description": "MODBUS-RTU example for reading Deye SG02LP1 solar inverter"
},
{
"fname": "the_pill/MODBUS/Deye/the_pill_mbsa_deye_vc.shelly.js",
"fname": "the_pill/MODBUS/Deye/deye_vc.shelly.js",
"title": "Deye SG02LP1 MODBUS-RTU + Virtual Components",
"description": "MODBUS-RTU reader for Deye SG02LP1 solar inverter with Virtual Component updates. Reads parameters over UART (RS485) and pushes values to user-defined virtual number components."
"description": "MODBUS-RTU reader for Deye SG02LP1 solar inverter with"
},
{
"fname": "the_pill/MODBUS/JK200-MBS/the_pill_mbsa_jk200.shelly.js",
"fname": "the_pill/MODBUS/JKESS/JK200-MBS/jk200.shelly.js",
"title": "JK200 BMS MODBUS-RTU Reader",
"description": "MODBUS-RTU reader for Jikong JK-PB series BMS over RS485."
},
{
"fname": "the_pill/MODBUS/JKESS/JK200-MBS/jk200_vc.shelly.js",
"title": "JK200 BMS MODBUS-RTU Reader + Virtual Components",
"description": "MODBUS-RTU reader for Jikong JK-PB series BMS over RS485 with"
},
{
"fname": "the_pill/MODBUS/LinkedGo/ST802/st802_bms.shelly.js",
"title": "LinkedGo ST802 Thermostat - BMS Modbus RTU Client",
"description": "Modbus RTU master that simulates BMS (Building Management System)"
},
{
"fname": "the_pill/MODBUS/LinkedGo/ST802/st802_bms_vc.shelly.js",
"title": "LinkedGo ST802 Thermostat - BMS Modbus RTU Client + Virtual Components",
"description": "Modbus RTU master that simulates BMS commands for the LinkedGo"
},
{
"fname": "the_pill/UART/uart_test.shelly.js",
"title": "UART test",
Expand Down
Loading