From f09c50101e32deb540b344c982b8933c57d36a02 Mon Sep 17 00:00:00 2001 From: Cyril Beslay Date: Thu, 25 Apr 2024 17:41:17 +0200 Subject: [PATCH] feat(scenes): Allow blinking switchs --- front/src/config/i18n/de.json | 6 +-- front/src/config/i18n/en.json | 10 ++-- front/src/config/i18n/fr.json | 10 ++-- .../routes/scene/edit-scene/ActionCard.jsx | 10 ++-- ...kLightParams.jsx => BlinkDeviceParams.jsx} | 34 +++++++------ .../actions/ChooseActionTypeCard.jsx | 2 +- server/lib/scene/scene.actions.js | 11 +++- ...t.js => scene.action.blinkDevices.test.js} | 51 ++++++++++++++++--- server/utils/constants.js | 2 +- 9 files changed, 93 insertions(+), 43 deletions(-) rename front/src/routes/scene/edit-scene/actions/{BlinkLightParams.jsx => BlinkDeviceParams.jsx} (75%) rename server/test/lib/scene/actions/{scene.action.blinkLights.test.js => scene.action.blinkDevices.test.js} (80%) diff --git a/front/src/config/i18n/de.json b/front/src/config/i18n/de.json index cbc9bbe528..7b419e618c 100644 --- a/front/src/config/i18n/de.json +++ b/front/src/config/i18n/de.json @@ -1684,8 +1684,8 @@ "label": "Wähle die Lichter aus, die umgeschaltet werden sollen", "description": "Diese Aktion schaltet das Licht ein, wenn es ausgeschaltet ist bzw. schaltet es aus, wenn es eingeschaltet ist" }, - "blinkLights": { - "label": "Wählen Sie die Lichter aus, die Sie zum Blinken bringen möchten", + "blinkDevices": { + "label": "Wählen Sie die Lichter/Schalter aus, die Sie blinken lassen möchten", "description": "Stellen Sie die Dauer und die Geschwindigkeit des Blinkens ein", "blinkingTime": { "label": "Dauer (in Sekunden)", @@ -1840,7 +1840,7 @@ "turn-on": "Licht einschalten", "turn-off": "Licht ausschalten", "toggle": "Lichter umschalten", - "blink": "Lichter blinken lassen" + "blink": "Lichter/Schalter blinken lassen" }, "switch": { "turn-on": "Schalter einschalten", diff --git a/front/src/config/i18n/en.json b/front/src/config/i18n/en.json index 630912132a..8fa57f355e 100644 --- a/front/src/config/i18n/en.json +++ b/front/src/config/i18n/en.json @@ -1686,8 +1686,8 @@ "label": "Select the lights you want to toggle", "description": "This action turn on the light if state is off or turn off the light if state is on" }, - "blinkLights": { - "label": "Select the lights you want to make blink", + "blinkDevices": { + "label": "Select the lights/switches you want to make blink", "description": "Configure blinking duration and speed", "blinkingTime": { "label": "Duration (in seconds)", @@ -1831,7 +1831,8 @@ }, "device": { "get-value": "Get device value", - "set-value": "Set device value" + "set-value": "Set device value", + "blink": "Make the Lights/Switches blink" }, "message": { "send": "Send Message", @@ -1841,8 +1842,7 @@ "light": { "turn-on": "Turn On the Lights", "turn-off": "Turn Off the Lights", - "toggle": "Toggle the Lights", - "blink": "Make the Lights blink" + "toggle": "Toggle the Lights" }, "switch": { "turn-on": "Turn On the Switches", diff --git a/front/src/config/i18n/fr.json b/front/src/config/i18n/fr.json index 74e11bcf48..c5108b8638 100644 --- a/front/src/config/i18n/fr.json +++ b/front/src/config/i18n/fr.json @@ -1688,8 +1688,8 @@ "label": "Sélectionnez les lumières que vous souhaitez inverser", "description": "Cette action allume la lumière si éteinte, sinon éteins la lumière" }, - "blinkLights": { - "label": "Sélectionnez les lumières que vous souhaitez faire clignoter", + "blinkDevices": { + "label": "Sélectionnez les lumières/prises que vous souhaitez faire clignoter", "description": "Réglez la durée et la vitesse de clignotement", "blinkingTime": { "label": "Durée (en secondes)", @@ -1833,7 +1833,8 @@ }, "device": { "get-value": "Récupérer le dernier état", - "set-value": "Contrôler un appareil" + "set-value": "Contrôler un appareil", + "blink": "Faire clignoter les lumières/prises" }, "message": { "send": "Envoyer un message", @@ -1843,8 +1844,7 @@ "light": { "turn-on": "Allumer les lumières", "turn-off": "Eteindre les lumières", - "toggle": "Inverser les lumières", - "blink": "Faire clignoter les lumières" + "toggle": "Inverser les lumières" }, "switch": { "turn-on": "Allumer les prises", diff --git a/front/src/routes/scene/edit-scene/ActionCard.jsx b/front/src/routes/scene/edit-scene/ActionCard.jsx index 5cf5bd784f..192301d014 100644 --- a/front/src/routes/scene/edit-scene/ActionCard.jsx +++ b/front/src/routes/scene/edit-scene/ActionCard.jsx @@ -15,7 +15,7 @@ import DeviceSetValue from './actions/DeviceSetValue'; import SendMessageParams from './actions/SendMessageParams'; import OnlyContinueIfParams from './actions/only-continue-if/OnlyContinueIfParams'; import TurnOnOffLightParams from './actions/TurnOnOffLightParams'; -import BlinkLightParams from './actions/BlinkLightParams'; +import BlinkDeviceParams from './actions/BlinkDeviceParams'; import TurnOnOffSwitchParams from './actions/TurnOnOffSwitchParams'; import StartSceneParams from './actions/StartSceneParams'; import UserPresence from './actions/UserPresence'; @@ -39,7 +39,7 @@ const ACTION_ICON = { [ACTIONS.LIGHT.TURN_ON]: 'fe fe-toggle-right', [ACTIONS.LIGHT.TURN_OFF]: 'fe fe-toggle-left', [ACTIONS.LIGHT.TOGGLE]: 'fe fe-shuffle', - [ACTIONS.LIGHT.BLINK]: 'fe fe-star', + [ACTIONS.DEVICE.BLINK]: 'fe fe-star', [ACTIONS.SWITCH.TURN_ON]: 'fe fe-toggle-right', [ACTIONS.SWITCH.TURN_OFF]: 'fe fe-toggle-left', [ACTIONS.SWITCH.TOGGLE]: 'fe fe-shuffle', @@ -100,7 +100,7 @@ const ActionCard = ({ children, ...props }) => { props.action.type === ACTIONS.MESSAGE.SEND || props.action.type === ACTIONS.CALENDAR.IS_EVENT_RUNNING || props.action.type === ACTIONS.MQTT.SEND || - props.action.type === ACTIONS.LIGHT.BLINK, + props.action.type === ACTIONS.DEVICE.BLINK, 'col-lg-4': props.action.type !== ACTIONS.CONDITION.ONLY_CONTINUE_IF && props.action.type !== ACTIONS.MESSAGE.SEND && @@ -176,8 +176,8 @@ const ActionCard = ({ children, ...props }) => { updateActionProperty={props.updateActionProperty} /> )} - {props.action.type === ACTIONS.LIGHT.BLINK && ( - { try { - const devices = await this.props.httpClient.get('/api/v1/device', { + const lightDevices = await this.props.httpClient.get('/api/v1/device', { device_feature_category: 'light', device_feature_type: 'binary' }); - const deviceOptions = devices.map(device => ({ + const switchDevices = await this.props.httpClient.get('/api/v1/device', { + device_feature_category: 'switch', + device_feature_type: 'binary' + }); + const deviceOptions = [...lightDevices, ...switchDevices].map(device => ({ value: device.selector, label: device.name })); @@ -23,8 +27,8 @@ class BlinkLight extends Component { }; handleChange = selectedOptions => { if (selectedOptions) { - const lights = selectedOptions.map(selectedOption => selectedOption.value); - this.props.updateActionProperty(this.props.columnIndex, this.props.index, 'devices', lights); + const devices = selectedOptions.map(selectedOption => selectedOption.value); + this.props.updateActionProperty(this.props.columnIndex, this.props.index, 'devices', devices); } else { this.props.updateActionProperty(this.props.columnIndex, this.props.index, 'devices', []); } @@ -39,8 +43,8 @@ class BlinkLight extends Component { refreshSelectedOptions = nextProps => { const selectedOptions = []; if (nextProps.action.devices && this.state.deviceOptions) { - nextProps.action.devices.forEach(light => { - const deviceOption = this.state.deviceOptions.find(deviceOption => deviceOption.value === light); + nextProps.action.devices.forEach(device => { + const deviceOption = this.state.deviceOptions.find(deviceOption => deviceOption.value === device); if (deviceOption) { selectedOptions.push(deviceOption); } @@ -73,7 +77,7 @@ class BlinkLight extends Component {
- +
} + placeholder={} />
@@ -105,7 +109,7 @@ class BlinkLight extends Component {
- +
@@ -130,4 +134,4 @@ class BlinkLight extends Component { } } -export default connect('httpClient', {})(BlinkLight); +export default connect('httpClient', {})(BlinkDeviceParams); diff --git a/front/src/routes/scene/edit-scene/actions/ChooseActionTypeCard.jsx b/front/src/routes/scene/edit-scene/actions/ChooseActionTypeCard.jsx index 61d315c8ef..02efc37a21 100644 --- a/front/src/routes/scene/edit-scene/actions/ChooseActionTypeCard.jsx +++ b/front/src/routes/scene/edit-scene/actions/ChooseActionTypeCard.jsx @@ -9,7 +9,7 @@ const ACTION_LIST = [ ACTIONS.LIGHT.TURN_ON, ACTIONS.LIGHT.TURN_OFF, ACTIONS.LIGHT.TOGGLE, - ACTIONS.LIGHT.BLINK, + ACTIONS.DEVICE.BLINK, ACTIONS.SWITCH.TURN_ON, ACTIONS.SWITCH.TURN_OFF, ACTIONS.SWITCH.TOGGLE, diff --git a/server/lib/scene/scene.actions.js b/server/lib/scene/scene.actions.js index 6a53779157..4b8bd51b92 100644 --- a/server/lib/scene/scene.actions.js +++ b/server/lib/scene/scene.actions.js @@ -110,7 +110,7 @@ const actionsFunc = { } }); }, - [ACTIONS.LIGHT.BLINK]: async (self, action, scope) => { + [ACTIONS.DEVICE.BLINK]: async (self, action, scope) => { const blinkingSpeed = action.blinking_speed; const blinkingTime = action.blinking_time * 1000 + 1; let blinkingInterval; @@ -131,11 +131,18 @@ const actionsFunc = { await Promise.map(action.devices, async (deviceSelector) => { try { const device = self.stateManager.get('device', deviceSelector); - const deviceFeature = getDeviceFeature( + let deviceFeature = getDeviceFeature( device, DEVICE_FEATURE_CATEGORIES.LIGHT, DEVICE_FEATURE_TYPES.LIGHT.BINARY, ); + if (!deviceFeature) { + deviceFeature = getDeviceFeature( + device, + DEVICE_FEATURE_CATEGORIES.SWITCH, + DEVICE_FEATURE_TYPES.SWITCH.BINARY, + ); + } const oldValue = deviceFeature.last_value; let newValue = 0; /* eslint-disable no-await-in-loop */ diff --git a/server/test/lib/scene/actions/scene.action.blinkLights.test.js b/server/test/lib/scene/actions/scene.action.blinkDevices.test.js similarity index 80% rename from server/test/lib/scene/actions/scene.action.blinkLights.test.js rename to server/test/lib/scene/actions/scene.action.blinkDevices.test.js index 124f7595b8..006094713c 100644 --- a/server/test/lib/scene/actions/scene.action.blinkLights.test.js +++ b/server/test/lib/scene/actions/scene.action.blinkDevices.test.js @@ -8,7 +8,7 @@ const StateManager = require('../../../../lib/state'); const event = new EventEmitter(); -describe('scene.blink-lights', () => { +describe('scene.blink-devices', () => { let clock; beforeEach(() => { @@ -43,7 +43,7 @@ describe('scene.blink-lights', () => { [ [ { - type: ACTIONS.LIGHT.BLINK, + type: ACTIONS.DEVICE.BLINK, devices: ['light-1'], blinking_speed: 'slow', blinking_time: 2, @@ -82,7 +82,7 @@ describe('scene.blink-lights', () => { [ [ { - type: ACTIONS.LIGHT.BLINK, + type: ACTIONS.DEVICE.BLINK, devices: ['light-1'], blinking_speed: 'medium', blinking_time: 2, @@ -121,7 +121,7 @@ describe('scene.blink-lights', () => { [ [ { - type: ACTIONS.LIGHT.BLINK, + type: ACTIONS.DEVICE.BLINK, devices: ['light-1'], blinking_speed: 'fast', blinking_time: 2, @@ -136,6 +136,45 @@ describe('scene.blink-lights', () => { assert.callCount(device.setValue, 12); }); + it('should blink switch in fast mode', async () => { + const stateManager = new StateManager(event); + const deviceFeature = { + category: DEVICE_FEATURE_CATEGORIES.SWITCH, + type: DEVICE_FEATURE_TYPES.SWITCH.BINARY, + last_value: 0, + }; + const device = { + setValue: fake.resolves(null), + features: { + category: DEVICE_FEATURE_CATEGORIES.SWITCH, + type: DEVICE_FEATURE_TYPES.SWITCH.BINARY, + find: fake.returns(deviceFeature), + }, + }; + + stateManager.setState('device', 'switch-1', device); + + const scope = {}; + executeActions( + { stateManager, event, device }, + [ + [ + { + type: ACTIONS.DEVICE.BLINK, + devices: ['switch-1'], + blinking_speed: 'fast', + blinking_time: 2, + }, + ], + ], + scope, + ); + await clock.tickAsync(3000); + assert.calledWithExactly(device.setValue, device, deviceFeature, 0); + assert.calledWithExactly(device.setValue, device, deviceFeature, 1); + assert.callCount(device.setValue, 12); + }); + it('should blink light in unknown mode', async () => { const stateManager = new StateManager(event); const deviceFeature = { @@ -160,7 +199,7 @@ describe('scene.blink-lights', () => { [ [ { - type: ACTIONS.LIGHT.BLINK, + type: ACTIONS.DEVICE.BLINK, devices: ['light-1'], blinking_speed: 'unknown', blinking_time: 2, @@ -192,7 +231,7 @@ describe('scene.blink-lights', () => { [ [ { - type: ACTIONS.LIGHT.BLINK, + type: ACTIONS.DEVICE.BLINK, devices: ['my-device'], blinking_speed: 'slow', blinking_time: 1, diff --git a/server/utils/constants.js b/server/utils/constants.js index 908a28f72f..c9598ac6a8 100644 --- a/server/utils/constants.js +++ b/server/utils/constants.js @@ -335,12 +335,12 @@ const ACTIONS = { DEVICE: { SET_VALUE: 'device.set-value', GET_VALUE: 'device.get-value', + BLINK: 'device.blink', }, LIGHT: { TURN_ON: 'light.turn-on', TURN_OFF: 'light.turn-off', TOGGLE: 'light.toggle', - BLINK: 'light.blink', }, SWITCH: { TURN_ON: 'switch.turn-on',