@ray-js/electrician-timing-sdk
v1.0.2-beta.1
Published
`@ray-js/electrician-timing-sdk` provides a unified timing solution for electrician devices, including:
Readme
Electrician Timing SDK
@ray-js/electrician-timing-sdk provides a unified timing solution for electrician devices, including:
- Electrician timers (cycle / random / inching)
- Countdown
- Cloud timers
- Conflict detection and conflict resolution
- Online status checks
Installation
npm i @ray-js/electrician-timing-sdkAPI Overview
Lifecycle
| API | Description |
| --- | --- |
| init(options) | Initialize SDK and load runtime state |
| changeConfig(options) | Update config; re-init when target device/group changes |
| destroy() | Clear internal state, listeners, and config |
Cloud Timer
| API | Description |
| --- | --- |
| addCloudTimer(data, option?) | Add one cloud timer |
| batchAddCloudTimer(dataList, option?) | Add cloud timers in batch |
| updateCloudTimer(data, option?) | Update cloud timer content |
| updateCloudTimerStatus(data, option?) | Enable/disable cloud timer |
| removeCloudTimer(id) | Remove cloud timer |
| onCloudUpdate(cb) | Subscribe cloud timer update event |
| offCloudUpdate(cb) | Unsubscribe cloud timer update event |
Countdown
| API | Description |
| --- | --- |
| createCountdown(code, countdown, option?) | Create countdown |
| cancelCountdown(code) | Cancel countdown |
Custom DP Timer
| API | Description |
| --- | --- |
| addDpTimer(code, data, option?) | Add custom DP timer |
| updateDpTimer(code, data, option?) | Update custom DP timer |
| updateDpTimerStatus(code, id, status, option?) | Enable/disable custom DP timer |
| removeDpTimer(code, id) | Remove custom DP timer |
Electrician Shortcuts (electri)
| API | Description |
| --- | --- |
| electri.cycle.add/update/updateStatus/remove | CRUD + status for cycle timer |
| electri.cycle.getConfig/validateMax/validateRepeat | Cycle timer config and validation |
| electri.random.add/update/updateStatus/remove | CRUD + status for random timer |
| electri.random.getConfig/validateMax/validateRepeat | Random timer config and validation |
| electri.inching.add/update/updateStatus/remove | CRUD + status for inching timer |
| electri.inching.getConfig/validateMax/validateRepeat | Inching timer config and validation |
Online Status
| API | Description |
| --- | --- |
| isLANOnline() | Check LAN-online status |
| isLocalOnline() | Check local-online status |
Initialization
Basic rules
- You must provide at least one of
devIdorgroupId. devIdtakes priority when both are provided.typesupportseleandcustom.
Common options of init(options)
| Field | Required | Description |
| --- | --- | --- |
| devId | No | Device ID |
| groupId | No | Group ID |
| type | Yes | ele or custom |
| category | No | Cloud timer category, default sdk_schedule,Modifications to new projects are not recommended|
| conflictModallId | No | Default conflict modal id |
| is24Hour | No | 24-hour display |
| combineSameData | No | Merge same timer data across channels, default true |
Extra options for type: 'ele'
| Field | Required | Description |
| --- | --- | --- |
| switches | No | Switch codes; auto-detected when omitted |
| countdowns | No | Countdown config list or countdown code list |
| dpTimerConfig | No | Custom DP timer config map |
| supportCycle/supportRandom/supportInching/supportCloud | No | Capability flag: auto / y / n |
| cycleCode/randomCode/inchingCode | No | Explicit timer dp code |
Extra options for type: 'custom'
| Field | Required | Description |
| --- | --- | --- |
| switches | Yes | Switch code list |
| countdowns | Yes | Countdown config list |
| dpTimerConfig | Yes | Custom timer dp config map |
| supportCloud | No | Cloud timer capability |
Conflict modal (ConflictPopup)
When timer APIs are called with { useDefaultModal: true }, the SDK resolves conflicts by taking the top page in the stack, calling selectComponent('#<id>') on the mounted conflict component, and invoking show(conflictData, validateData) to render the conflict list. After the user confirms, the component runs the same resolution path as the main package (DP publish / cloud timers, etc.). Therefore conflictModallId passed to init (default smart-conflict-popup) must exactly match the popup node id in your page; otherwise the SDK throws because the component cannot be found.
flowchart TB
A[Timer API + useDefaultModal: true] --> B[SDK validates conflicts]
B -->|No conflict| C[Continue / pass]
B -->|Conflict| D["selectComponent('#conflictModallId').show(...)"]
D --> E[ConflictPopup renders list]
E --> F{User action}
F -->|Confirm| G[Internal resolve applies changes]
F -->|Cancel/close| H[API returns cancel]
G --> I[success, or toast + reject on failure]Using ConflictPopup in React
import { ConflictPopup } from '@ray-js/electrician-timing-sdk/lib/components';
// Mount near the page root; id must match init({ conflictModallId }) (default can be omitted)
<ConflictPopup
id="smart-conflict-popup"
title="Timer conflict"
description="Replace conflicting timers?"
locale={locale}
cancelText="Cancel"
okText="Confirm"
/>List content is injected when the SDK calls show; you normally only set title, description, locale, and button labels. Follow your Ray + React build setup for component registration.
ConflictPopup props
| Prop | Required | Description |
| --- | --- | --- |
| title | Yes | Modal title |
| locale | Yes | Locale object: weekdays, type labels, conflictFailure, DP strings, etc. |
| id | No | Must match init’s conflictModallId for selectComponent |
| description | No | Subtitle / helper text |
| cancelText / okText | No | Button labels (defaults exist) |
| themeColor | No | Icon background color |
| hideMask | No | Hide overlay mask |
| visble | No | Visibility flag (same spelling as source; show usually drives display) |
| usesolt | No | Use slot for custom list area (same spelling as source) |
| data / validateData | No | Normally passed by SDK in show, not hard-coded in template |
Complete API Examples
1) Initialize
flowchart LR
A[Pass devId/groupId + type] --> B[init loads runtime state]
B --> C[Cloud/electri/countdown capabilities]
C --> D[Ready for timer APIs]import { init } from '@ray-js/electrician-timing-sdk';
await init({
devId: 'your-device-id',
type: 'ele',
supportCloud: 'auto',
});2) Cycle timer
flowchart LR
A[Build cycle timer data] --> B[electri.cycle.add]
B --> C{Conflict check}
C -->|Pass| D[Publish DP / success]
C -->|Conflict| E[Return conflict + validateData]
C -->|Cancel| F[cancel]import { electri } from '@ray-js/electrician-timing-sdk';
await electri.cycle.add(
{
id: -1,
type: 'sdk_cycle',
startTime: 8 * 60,
endTime: 18 * 60,
week: [1, 1, 1, 1, 1, 0, 0],
status: true,
actions: [{ code: 'switch_1' }],
onHoldTime: 100,
offHoldTime: 100,
},
{ useDefaultModal: true }
);3) Random timer
flowchart LR
A[Build random timer data] --> B[electri.random.add]
B --> C{Conflict check}
C -->|Pass| D[Publish DP / success]
C -->|Conflict| E[Return conflict + validateData]
C -->|Cancel| F[cancel]import { electri } from '@ray-js/electrician-timing-sdk';
await electri.random.add(
{
id: -1,
type: 'sdk_random',
startTime: 10 * 60,
endTime: 12 * 60,
week: [0, 0, 1, 0, 0, 0, 0],
status: true,
actions: [{ code: 'switch_1' }],
},
{ useDefaultModal: true }
);4) Inching timer
flowchart LR
A[Build inching data time + actions] --> B[electri.inching.add]
B --> C{Conflict check}
C -->|Pass| D[Publish DP / success]
C -->|Conflict| E[Return conflict + validateData]
C -->|Cancel| F[cancel]import { electri } from '@ray-js/electrician-timing-sdk';
await electri.inching.add(
{
id: -1,
type: 'sdk_inching',
time: 300,
status: true,
actions: [{ code: 'switch_1' }],
},
{ useDefaultModal: true }
);5) Cloud timer (single + batch)
flowchart TB
subgraph single["Single add"]
S1[addCloudTimer single data] --> S2{Conflict check}
S2 --> S3[success / cancel / conflict]
end
subgraph batch["Batch add"]
B1[batchAddCloudTimer data list] --> B2{Conflict check}
B2 --> B3[success / cancel / conflict]
endimport { addCloudTimer, batchAddCloudTimer } from '@ray-js/electrician-timing-sdk';
await addCloudTimer(
{
aliasName: 'morning',
startTime: 9 * 60,
week: [1, 1, 1, 1, 1, 1, 1],
status: true,
actions: [{ code: 'switch_1', value: true }],
isAppPush: false,
},
{ useDefaultModal: true }
);
await batchAddCloudTimer(
[
{
aliasName: 'workday',
startTime: 8 * 60,
week: [1, 1, 1, 1, 1, 0, 0],
status: true,
actions: [{ code: 'switch_1', value: true }],
isAppPush: false,
},
],
{ useDefaultModal: true }
);6) Countdown
flowchart LR
A[createCountdown code + duration] --> B{Conflict check}
B -->|Pass| C[Publish countdown DP]
B -->|Conflict/Cancel| D[Return result]
C --> E[Optional: cancelCountdown]import { createCountdown, cancelCountdown } from '@ray-js/electrician-timing-sdk';
await createCountdown('countdown_1', 1800, { useDefaultModal: true });
await cancelCountdown('countdown_1');7) Custom DP timer
flowchart TB
A[addDpTimer code + data] --> B{Conflict check}
B --> C[success / conflict]
C --> D[updateDpTimerStatus enable/disable]
C --> E[removeDpTimer delete]
D --> F[Maintain lifecycle]
E --> Fimport { addDpTimer, updateDpTimerStatus, removeDpTimer } from '@ray-js/electrician-timing-sdk';
await addDpTimer(
'cycle_timing',
{
id: 1,
type: 'sdk_cycle',
startTime: 360,
endTime: 480,
week: [1, 1, 1, 1, 1, 1, 1],
status: true,
actions: [{ code: 'switch_1' }],
onHoldTime: 60,
offHoldTime: 60,
},
{ useDefaultModal: true }
);
await updateDpTimerStatus('cycle_timing', 1, false);
await removeDpTimer('cycle_timing', 1);Recommended Timing Workflow
Use this order for stable behavior:
- Initialize with
init(options)before any timer API call. - Check capability (cloud/electri/countdown) based on product needs.
- Create timer via one of:
electri.*,addCloudTimer,createCountdown,addDpTimer. - Handle conflict result:
success: done.cancel: user canceled conflict handling.{ conflict, validateData }: continue with your conflict UI/process.
- Maintain timer lifecycle with
update*andupdate*Status. - Listen for updates using
onConflictChangeandonCloudUpdate. - Cleanup with
off*listeners anddestroy()when leaving page/scene.
Conflict-related return values
success: operation completedcancel: user canceled conflict handlingpass: internal "validated, continue" state{ conflict, validateData }: conflict detail payload
Error Codes
| errCode | errMsg | | --- | --- | | 1001 | Supports a maximum of timers | | 1002 | Timer dp config not found | | 1003 | Timer id not found | | 1004 | Cloud timer not supported | | 1005 | Countdown cancel value is missing | | 1006 | Countdown config not found | | 1007 | DP schema not found | | 1008 | Invalid value | | 1009 | Cycle start time and end time cannot be equal | | 1010 | Loop unit duration cannot exceed total duration | | 1011 | Random timer duration must be at least 30 minutes |
Notes
- Cloud timer is not supported in group mode by default.
- Conflict validation happens on enable-path operations (create/update-enable/enable status).
- For enum-based countdown total values, configure
totalRangeandcancelValuecorrectly. combineSameDatachanges how same-content timers across channels are merged.
