Refactor ceiling sensor functions and update slider helper mappings for improved value handling

This commit is contained in:
Faris Armoush
2025-04-14 16:24:50 +03:00
parent 1493e35f6a
commit ebcd89d2a5
4 changed files with 68 additions and 39 deletions

View File

@ -1,7 +1,6 @@
import 'package:syncrow_web/pages/routines/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
// TODO: functions in conditions / status in actions
class CpsOperationalValue { class CpsOperationalValue {
final String icon; final String icon;
final String description; final String description;
@ -223,7 +222,6 @@ final class CpsSpatialMotionValueFunction extends CpsFunctions {
} }
final class CpsMaxDistanceOfDetectionFunction extends CpsFunctions { final class CpsMaxDistanceOfDetectionFunction extends CpsFunctions {
// confirm with BE
CpsMaxDistanceOfDetectionFunction({ CpsMaxDistanceOfDetectionFunction({
required super.deviceId, required super.deviceId,
required super.deviceName, required super.deviceName,
@ -267,7 +265,7 @@ final class CpsMaxDistanceOfStaticDetectionFunction extends CpsFunctions {
max = 10.0, max = 10.0,
step = 0.5, step = 0.5,
super( super(
code: 'static_max_dis', // 0 / 500 code: 'static_max_dis',
operationName: 'Maximum Distance Of Static Detection', operationName: 'Maximum Distance Of Static Detection',
icon: Assets.currentDistanceIcon, icon: Assets.currentDistanceIcon,
); );
@ -302,7 +300,7 @@ final class CpsDetectionRangeFunction extends CpsFunctions {
max = 25.5, max = 25.5,
step = 0.1, step = 0.1,
super( super(
code: 'moving_range', // just then code: 'moving_range',
operationName: 'Detection Range', operationName: 'Detection Range',
icon: Assets.farDetection, icon: Assets.farDetection,
); );
@ -372,7 +370,7 @@ final class CpsPresenceJudgementThrsholdFunction extends CpsFunctions {
max = 255, max = 255,
step = 5, step = 5,
super( super(
code: 'presence_reference', // max 255 // change widget code: 'presence_reference',
operationName: 'Presence Judgement Threshold', operationName: 'Presence Judgement Threshold',
icon: Assets.presenceJudgementThrshold, icon: Assets.presenceJudgementThrshold,
); );
@ -403,7 +401,7 @@ final class CpsMotionAmplitudeTriggerThresholdFunction extends CpsFunctions {
max = 255, max = 255,
step = 5, step = 5,
super( super(
code: 'moving_reference', // max 255 // change widget code: 'moving_reference',
operationName: 'Motion Amplitude Trigger Threshold', operationName: 'Motion Amplitude Trigger Threshold',
icon: Assets.presenceJudgementThrshold, icon: Assets.presenceJudgementThrshold,
); );
@ -434,7 +432,7 @@ final class CpsPerpetualBoundaryFunction extends CpsFunctions {
max = 5.00, max = 5.00,
step = 0.50, step = 0.50,
super( super(
code: 'perceptual_boundary', // 0 / 500 code: 'perceptual_boundary',
operationName: 'Perpetual Boundary', operationName: 'Perpetual Boundary',
icon: Assets.boundary, icon: Assets.boundary,
); );
@ -469,7 +467,7 @@ final class CpsMotionTriggerBoundaryFunction extends CpsFunctions {
max = 5.0, max = 5.0,
step = 0.5, step = 0.5,
super( super(
code: 'moving_boundary', // 0 / 500 / step 50 code: 'moving_boundary',
operationName: 'Motion Trigger Boundary', operationName: 'Motion Trigger Boundary',
icon: Assets.motionMeter, icon: Assets.motionMeter,
); );
@ -504,7 +502,7 @@ final class CpsMotionTriggerTimeFunction extends CpsFunctions {
max = 2.0, max = 2.0,
step = 0.1, step = 0.1,
super( super(
code: 'moving_rigger_time', // 0 / 2000 steps 10 code: 'moving_rigger_time',
operationName: 'Motion Trigger Time', operationName: 'Motion Trigger Time',
icon: Assets.motionMeter, icon: Assets.motionMeter,
); );
@ -539,7 +537,7 @@ final class CpsMotionToStaticTimeFunction extends CpsFunctions {
max = 50.0, max = 50.0,
step = 1.0, step = 1.0,
super( super(
code: 'moving_static_time', // 0 / 6000 steps 100 code: 'moving_static_time',
operationName: 'Motion To Static Time', operationName: 'Motion To Static Time',
icon: Assets.motionMeter, icon: Assets.motionMeter,
); );
@ -574,7 +572,7 @@ final class CpsEnteringNoBodyStateTimeFunction extends CpsFunctions {
max = 300.0, max = 300.0,
step = 5.0, step = 5.0,
super( super(
code: 'none_body_time', // 0 / 300000 / steps 500 code: 'none_body_time',
operationName: 'Entering Nobody State Time', operationName: 'Entering Nobody State Time',
icon: Assets.motionMeter, icon: Assets.motionMeter,
); );
@ -606,7 +604,7 @@ final class CpsSelfTestResultFunctions extends CpsFunctions {
required super.deviceName, required super.deviceName,
required super.type, required super.type,
}) : super( }) : super(
code: 'checking_result', // just in action code: 'checking_result',
operationName: 'Self-Test Result', operationName: 'Self-Test Result',
icon: Assets.selfTestResult, icon: Assets.selfTestResult,
); );
@ -828,7 +826,7 @@ class CpsPresenceStatusFunctions extends CpsFunctions {
required super.deviceName, required super.deviceName,
required super.type, required super.type,
}) : super( }) : super(
code: 'presence_state', // just in action code: 'presence_state',
operationName: 'Presence Status', operationName: 'Presence Status',
icon: Assets.presenceSensor, icon: Assets.presenceSensor,
); );
@ -864,7 +862,7 @@ final class CpsSportsParaFunction extends CpsFunctions {
max = 100, max = 100,
step = 1, step = 1,
super( super(
code: 'sports_para', // just in action code: 'sports_para',
operationName: 'Sports Para', operationName: 'Sports Para',
icon: Assets.sportsPara, icon: Assets.sportsPara,
); );

View File

@ -11,6 +11,7 @@ import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_senso
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_dialog_slider_selector.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_dialog_slider_selector.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_dialog_value_selector.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_dialog_value_selector.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_functions_list.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_functions_list.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_slider_helpers.dart';
class CeilingSensorDialog extends StatefulWidget { class CeilingSensorDialog extends StatefulWidget {
const CeilingSensorDialog({ const CeilingSensorDialog({
@ -76,7 +77,8 @@ class _CeilingSensorDialogState extends State<CeilingSensorDialog> {
? () { ? () {
context.read<RoutineBloc>().add( context.read<RoutineBloc>().add(
AddFunctionToRoutine( AddFunctionToRoutine(
state.addedFunctions, _updateValuesForAddedFunctions(
state.addedFunctions),
'${widget.uniqueCustomId}', '${widget.uniqueCustomId}',
), ),
); );
@ -150,15 +152,58 @@ class _CeilingSensorDialogState extends State<CeilingSensorDialog> {
], ],
); );
} }
List<DeviceFunctionData> updateValuesForAddedFunctions(List<DeviceFunctionData> addedFunctions) {
List<DeviceFunctionData> _updateValuesForAddedFunctions(
List<DeviceFunctionData> addedFunctions,
) {
const mappableSteppedFunctions = <String>{
'static_max_dis',
'presence_reference',
'moving_reference',
'perceptual_boundary',
'moving_boundary',
'moving_rigger_time',
'moving_static_time',
'none_body_time',
'moving_max_dis',
};
return addedFunctions.map((function) { return addedFunctions.map((function) {
if (function.functionCode == 'sensitivity') { if (mappableSteppedFunctions.contains(function.functionCode)) {
return function.copyWith( final mappedValue = mapSteppedValue(
value: function.value, value: function.value,
inputStep: CpsSliderHelpers.dividendOfRange(function.functionCode),
inputRange: CpsSliderHelpers.sliderRange(function.functionCode),
outputRange: CpsSliderHelpers.mappedRange(function.functionCode),
);
return DeviceFunctionData(
value: mappedValue,
entityId: function.entityId,
functionCode: function.functionCode,
operationName: function.operationName,
condition: function.condition, condition: function.condition,
actionExecutor: function.actionExecutor,
valueDescription: function.valueDescription,
); );
} }
return function; return function;
}).toList(); }).toList();
} }
int mapSteppedValue({
required (double min, double max) inputRange,
required double inputStep,
required (double min, double max, double dividend) outputRange,
required double value,
}) {
final (inputMin, inputMax) = inputRange;
final (outputMin, outputMax, outputStep) = outputRange;
final clampedValue = value.clamp(inputMin, inputMax);
final stepsFromMin = ((clampedValue - inputMin) / inputStep).round();
final mappedValue = outputMin + (stepsFromMin * outputStep);
return mappedValue.clamp(outputMin, outputMax).round();
}
} }

View File

@ -66,22 +66,4 @@ class CpsDialogSliderSelector extends StatelessWidget {
), ),
); );
} }
double reverseMappedValue(double value) {
final (inputMin, inputMax) =
CpsSliderHelpers.sliderRange(selectedFunctionData.functionCode);
final (outputMin, outputMax, outputStep) = CpsSliderHelpers.mappedRange(
selectedFunctionData.functionCode,
);
final clampedValue = value.clamp(outputMin, outputMax);
final stepsFromMin = ((clampedValue - outputMin) / outputStep).round();
final mappedValue = inputMin +
(stepsFromMin *
CpsSliderHelpers.dividendOfRange(selectedFunctionData.functionCode));
return mappedValue.clamp(inputMin, inputMax);
}
} }

View File

@ -4,13 +4,14 @@ abstract final class CpsSliderHelpers {
final defaultDivdidend = dividendOfRange(functionCode); final defaultDivdidend = dividendOfRange(functionCode);
return switch (functionCode) { return switch (functionCode) {
'static_max_dis' => (0, 500, 50), 'static_max_dis' => (0, 500, 50),
'presence_reference' => (0, 255, 50), 'presence_reference' => (0, 255, 5),
'moving_reference' => (0, 255, 5), 'moving_reference' => (0, 255, 5),
'perceptual_boundary' => (0, 500, 50), 'perceptual_boundary' => (0, 500, 50),
'moving_boundary' => (0, 500, 50), 'moving_boundary' => (0, 500, 50),
'moving_rigger_time' => (0, 2000, 100), 'moving_rigger_time' => (0, 2000, 100),
'moving_static_time' => (0, 6000, 100), 'moving_static_time' => (0, 60000, 1000),
'none_body_time' => (0, 300000, 500), 'none_body_time' => (0, 300000, 5000),
'moving_max_dis' => (0, 500, 50),
_ => (defaultMin, defaultMax, defaultDivdidend), _ => (defaultMin, defaultMax, defaultDivdidend),
}; };
} }
@ -83,4 +84,7 @@ abstract final class CpsSliderHelpers {
_ => '${parsedValue?.toStringAsFixed(0) ?? 0}', _ => '${parsedValue?.toStringAsFixed(0) ?? 0}',
}; };
} }
// TODO: Sports Para causes 400 in IF and THEN / sports_para
// TODO: Detection range causes 400 in IF / moving_range
// TODO: Distance of moving objects causes 400 in IF / presence_range
} }