diff --git a/assets/icons/energy_consumed_icon.svg b/assets/icons/energy_consumed_icon.svg
new file mode 100644
index 00000000..d457619c
--- /dev/null
+++ b/assets/icons/energy_consumed_icon.svg
@@ -0,0 +1,10 @@
+
diff --git a/lib/pages/device_managment/all_devices/models/devices_model.dart b/lib/pages/device_managment/all_devices/models/devices_model.dart
index de1b7632..808a683f 100644
--- a/lib/pages/device_managment/all_devices/models/devices_model.dart
+++ b/lib/pages/device_managment/all_devices/models/devices_model.dart
@@ -12,6 +12,7 @@ import 'package:syncrow_web/pages/routines/models/gang_switches/one_gang_switch/
import 'package:syncrow_web/pages/routines/models/gang_switches/three_gang_switch/three_gang_switch.dart';
import 'package:syncrow_web/pages/routines/models/gang_switches/two_gang_switch/two_gang_switch.dart';
import 'package:syncrow_web/pages/routines/models/gateway.dart';
+import 'package:syncrow_web/pages/routines/models/pc/energy_clamp_functions.dart';
import 'package:syncrow_web/pages/routines/models/water_heater/water_heater_functions.dart';
import 'package:syncrow_web/pages/routines/models/wps/wps_functions.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_sensor/ceiling_sensor_helper.dart';
@@ -248,6 +249,8 @@ SOS
tempIcon = Assets.waterLeakNormal;
} else if (type == DeviceType.NCPS) {
tempIcon = Assets.sensors;
+ } else if (type == DeviceType.PC) {
+ tempIcon = Assets.powerClamp;
} else {
tempIcon = Assets.logoHorizontal;
}
@@ -393,6 +396,59 @@ SOS
BacklightFunction(
deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
];
+ case 'PC':
+ return [
+ TotalEnergyConsumedStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ TotalActivePowerConsumedStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ VoltagePhaseSequenceDetectionFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ TotalCurrentStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ FrequencyStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+
+ // Phase A
+ EnergyConsumedAStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ ActivePowerAStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ VoltageAStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ PowerFactorAStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ CurrentAStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+
+ // Phase B
+ EnergyConsumedBStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ ActivePowerBStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ VoltageBStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ CurrentBStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ PowerFactorBStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+
+ // Phase C
+ EnergyConsumedCStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ ActivePowerCStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ VoltageCStatusFunction(
+ deviceId: uuid ?? '', deviceName: name ?? '', type: 'IF'),
+ CurrentCStatusFunction(
+ deviceId: uuid ?? '',
+ deviceName: name ?? '',
+ type: 'IF'),
+ PowerFactorCStatusFunction(
+ deviceId: uuid ?? '',
+ deviceName: name ?? '',
+ type: 'IF'),
+ ];
default:
return [];
@@ -526,5 +582,6 @@ SOS
"GD": DeviceType.GarageDoor,
"WL": DeviceType.WaterLeak,
"NCPS": DeviceType.NCPS,
+ "PC": DeviceType.PC,
};
}
diff --git a/lib/pages/routines/helper/dialog_helper/device_dialog_helper.dart b/lib/pages/routines/helper/dialog_helper/device_dialog_helper.dart
index bdba5797..df4683d8 100644
--- a/lib/pages/routines/helper/dialog_helper/device_dialog_helper.dart
+++ b/lib/pages/routines/helper/dialog_helper/device_dialog_helper.dart
@@ -7,6 +7,7 @@ import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_senso
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/flush_presence_sensor/flush_presence_sensor.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/gateway/gateway_helper.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/one_gang_switch_dialog.dart';
+import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/power_clamp_enargy/energy_clamp_dialog.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/three_gang_switch_dialog.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/two_gang_switch_dialog.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/wall_sensor/wall_presence_sensor.dart';
@@ -137,6 +138,16 @@ class DeviceDialogHelper {
device: data['device'],
);
+ case 'PC':
+ return EnergyClampDialog.showEnergyClampFunctionsDialog(
+ context: context,
+ functions: functions,
+ uniqueCustomId: data['uniqueCustomId'],
+ deviceSelectedFunctions: deviceSelectedFunctions,
+ dialogType: dialogType,
+ device: data['device'],
+ );
+
default:
return null;
}
diff --git a/lib/pages/routines/models/device_functions.dart b/lib/pages/routines/models/device_functions.dart
index b895dccc..40b26304 100644
--- a/lib/pages/routines/models/device_functions.dart
+++ b/lib/pages/routines/models/device_functions.dart
@@ -9,7 +9,6 @@ abstract class DeviceFunction {
final double? max;
final double? min;
-
DeviceFunction({
required this.deviceId,
required this.deviceName,
@@ -114,4 +113,28 @@ class DeviceFunctionData {
max.hashCode ^
min.hashCode;
}
+
+ DeviceFunctionData copyWith({
+ String? entityId,
+ String? functionCode,
+ String? operationName,
+ String? condition,
+ dynamic value,
+ double? step,
+ String? unit,
+ double? max,
+ double? min,
+ }) {
+ return DeviceFunctionData(
+ entityId: entityId ?? this.entityId,
+ functionCode: functionCode ?? this.functionCode,
+ operationName: operationName ?? this.operationName,
+ condition: condition ?? this.condition,
+ value: value ?? this.value,
+ step: step ?? this.step,
+ unit: unit ?? this.unit,
+ max: max ?? this.max,
+ min: min ?? this.min,
+ );
+ }
}
diff --git a/lib/pages/routines/models/pc/energy_clamp_functions.dart b/lib/pages/routines/models/pc/energy_clamp_functions.dart
new file mode 100644
index 00000000..4bf3ddd8
--- /dev/null
+++ b/lib/pages/routines/models/pc/energy_clamp_functions.dart
@@ -0,0 +1,416 @@
+import 'package:syncrow_web/pages/device_managment/power_clamp/models/power_clamp_batch_model.dart';
+import 'package:syncrow_web/pages/routines/models/device_functions.dart';
+import 'package:syncrow_web/pages/routines/models/pc/enrgy_clamp_operational_value.dart';
+import 'package:syncrow_web/utils/constants/assets.dart';
+
+abstract class EnergyClampFunctions extends DeviceFunction {
+ final String type;
+
+ EnergyClampFunctions({
+ required super.deviceId,
+ required super.deviceName,
+ required super.code,
+ required super.operationName,
+ required super.icon,
+ required this.type,
+ super.step,
+ super.unit,
+ super.max,
+ super.min,
+ });
+
+ List getOperationalValues();
+}
+
+// General & shared
+class TotalEnergyConsumedStatusFunction extends EnergyClampFunctions {
+ TotalEnergyConsumedStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'EnergyConsumed',
+ operationName: 'Total Energy Consumed',
+ icon: Assets.energyConsumedIcon,
+ min: 0.00,
+ max: 20000000.00,
+ step: 1,
+ unit: "kWh",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class TotalActivePowerConsumedStatusFunction extends EnergyClampFunctions {
+ TotalActivePowerConsumedStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'ActivePower',
+ operationName: 'Total Active Power',
+ icon: Assets.powerActiveIcon,
+ min: -19800000,
+ max: 19800000,
+ step: 0.1,
+ unit: "kW",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class VoltagePhaseSequenceDetectionFunction extends EnergyClampFunctions {
+ VoltagePhaseSequenceDetectionFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'voltage_phase_seq',
+ operationName: 'Voltage phase sequence detection',
+ icon: Assets.voltageIcon,
+ );
+
+ @override
+ List getOperationalValues() => [
+ EnergyClampOperationalValue(
+ icon: Assets.voltageIcon, description: '0', value: '0'),
+ EnergyClampOperationalValue(
+ icon: Assets.voltageIcon, description: '1', value: '1'),
+ EnergyClampOperationalValue(
+ icon: Assets.voltageIcon, description: '2', value: '2'),
+ EnergyClampOperationalValue(
+ icon: Assets.voltageIcon, description: '3', value: '3'),
+ EnergyClampOperationalValue(
+ icon: Assets.voltageIcon, description: '4', value: '4'),
+ EnergyClampOperationalValue(
+ icon: Assets.voltageIcon, description: '5', value: '5'),
+ ];
+}
+
+class TotalCurrentStatusFunction extends EnergyClampFunctions {
+ TotalCurrentStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'Current',
+ operationName: 'Total Current',
+ icon: Assets.voltMeterIcon,
+ min: 0.000,
+ max: 9000.000,
+ step: 1,
+ unit: "A",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class FrequencyStatusFunction extends EnergyClampFunctions {
+ FrequencyStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'Frequency',
+ operationName: 'Frequency',
+ icon: Assets.frequencyIcon,
+ min: 0,
+ max: 80,
+ step: 1,
+ unit: "Hz",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+// Phase A
+class EnergyConsumedAStatusFunction extends EnergyClampFunctions {
+ EnergyConsumedAStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'EnergyConsumedA',
+ operationName: 'Energy Consumed A',
+ icon: Assets.energyConsumedIcon,
+ min: 0.00,
+ max: 20000000.00,
+ step: 1,
+ unit: "kWh",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class ActivePowerAStatusFunction extends EnergyClampFunctions {
+ ActivePowerAStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'ActivePowerA',
+ operationName: 'Active Power A',
+ icon: Assets.powerActiveIcon,
+ min: 200,
+ max: 300,
+ step: 1,
+ unit: "kW",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class VoltageAStatusFunction extends EnergyClampFunctions {
+ VoltageAStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'VoltageA',
+ operationName: 'Voltage A',
+ icon: Assets.voltageIcon,
+ min: 0.0,
+ max: 500,
+ step: 1,
+ unit: "V",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class PowerFactorAStatusFunction extends EnergyClampFunctions {
+ PowerFactorAStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'PowerFactorA',
+ operationName: 'Power Factor A',
+ icon: Assets.speedoMeter,
+ min: 0.00,
+ max: 1.00,
+ step: 0.1,
+ unit: "",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class CurrentAStatusFunction extends EnergyClampFunctions {
+ CurrentAStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'CurrentA',
+ operationName: 'Current A',
+ icon: Assets.voltMeterIcon,
+ min: 0.000,
+ max: 3000.000,
+ step: 1,
+ unit: "A",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+// Phase B
+class EnergyConsumedBStatusFunction extends EnergyClampFunctions {
+ EnergyConsumedBStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'EnergyConsumedB',
+ operationName: 'Energy Consumed B',
+ icon: Assets.energyConsumedIcon,
+ min: 0.00,
+ max: 20000000.00,
+ step: 1,
+ unit: "kWh",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class ActivePowerBStatusFunction extends EnergyClampFunctions {
+ ActivePowerBStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'ActivePowerB',
+ operationName: 'Active Power B',
+ icon: Assets.powerActiveIcon,
+ min: -6600000,
+ max: 6600000,
+ step: 1,
+ unit: "kW",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class VoltageBStatusFunction extends EnergyClampFunctions {
+ VoltageBStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'VoltageB',
+ operationName: 'Voltage B',
+ icon: Assets.voltageIcon,
+ min: 0.0,
+ max: 500,
+ step: 1,
+ unit: "V",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class CurrentBStatusFunction extends EnergyClampFunctions {
+ CurrentBStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'CurrentB',
+ operationName: 'Current B',
+ icon: Assets.voltMeterIcon,
+ min: 0.000,
+ max: 3000.000,
+ step: 1,
+ unit: "A",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class PowerFactorBStatusFunction extends EnergyClampFunctions {
+ PowerFactorBStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'PowerFactorB',
+ operationName: 'Power Factor B',
+ icon: Assets.speedoMeter,
+ min: 0.0,
+ max: 1.0,
+ step: 0.1,
+ unit: "",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+// Phase C
+class EnergyConsumedCStatusFunction extends EnergyClampFunctions {
+ EnergyConsumedCStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'EnergyConsumedC',
+ operationName: 'Energy Consumed C',
+ icon: Assets.energyConsumedIcon,
+ min: 0.00,
+ max: 20000000.00,
+ step: 1,
+ unit: "kWh",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class ActivePowerCStatusFunction extends EnergyClampFunctions {
+ ActivePowerCStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'ActivePowerC',
+ operationName: 'Active Power C',
+ icon: Assets.powerActiveIcon,
+ min: -6600000,
+ max: 6600000,
+ step: 1,
+ unit: "kW",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class VoltageCStatusFunction extends EnergyClampFunctions {
+ VoltageCStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'VoltageC',
+ operationName: 'Voltage C',
+ icon: Assets.voltageIcon,
+ min: 0.00,
+ max: 500,
+ step: 0.1,
+ unit: "V",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class CurrentCStatusFunction extends EnergyClampFunctions {
+ CurrentCStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'CurrentC',
+ operationName: 'Current C',
+ icon: Assets.voltMeterIcon,
+ min: 0.000,
+ max: 3000.000,
+ step: 0.1,
+ unit: "A",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
+
+class PowerFactorCStatusFunction extends EnergyClampFunctions {
+ PowerFactorCStatusFunction({
+ required super.deviceId,
+ required super.deviceName,
+ required super.type,
+ }) : super(
+ code: 'PowerFactorC',
+ operationName: 'Power Factor C',
+ icon: Assets.speedoMeter,
+ min: 0.00,
+ max: 1.00,
+ step: 0.1,
+ unit: "",
+ );
+
+ @override
+ List getOperationalValues() => [];
+}
diff --git a/lib/pages/routines/models/pc/enrgy_clamp_operational_value.dart b/lib/pages/routines/models/pc/enrgy_clamp_operational_value.dart
new file mode 100644
index 00000000..5d89acf6
--- /dev/null
+++ b/lib/pages/routines/models/pc/enrgy_clamp_operational_value.dart
@@ -0,0 +1,11 @@
+class EnergyClampOperationalValue {
+ final String icon;
+ final String description;
+ final dynamic value;
+
+ EnergyClampOperationalValue({
+ required this.icon,
+ required this.description,
+ required this.value,
+ });
+}
diff --git a/lib/pages/routines/widgets/custom_routines_textbox.dart b/lib/pages/routines/widgets/custom_routines_textbox.dart
index e9ada1c2..f0767df4 100644
--- a/lib/pages/routines/widgets/custom_routines_textbox.dart
+++ b/lib/pages/routines/widgets/custom_routines_textbox.dart
@@ -40,6 +40,7 @@ class CustomRoutinesTextbox extends StatefulWidget {
class _CustomRoutinesTextboxState extends State {
late final TextEditingController _controller;
+
bool hasError = false;
String? errorMessage;
@@ -55,29 +56,63 @@ class _CustomRoutinesTextboxState extends State {
}
}
+ bool _isInitialized = false;
+
@override
void initState() {
super.initState();
- int decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
- double initialValue;
- if (widget.initialValue != null &&
- widget.initialValue is num &&
- (widget.initialValue as num) == 0) {
- initialValue = 0.0;
+ _initializeController();
+ }
+
+ void _initializeController() {
+ final decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
+ final dynamic initialValue = widget.initialValue;
+ double parsedValue;
+
+ if (initialValue is num) {
+ parsedValue = initialValue.toDouble();
+ } else if (initialValue is String) {
+ parsedValue = double.tryParse(initialValue) ?? widget.sliderRange.$1;
} else {
- initialValue = double.tryParse(widget.displayedValue) ?? 0.0;
+ parsedValue = widget.sliderRange.$1;
}
+
_controller = TextEditingController(
- text: initialValue.toStringAsFixed(decimalPlaces),
+ text: parsedValue.toStringAsFixed(decimalPlaces),
);
+ _isInitialized = true;
}
@override
- void dispose() {
- _controller.dispose();
- super.dispose();
+ void didUpdateWidget(CustomRoutinesTextbox oldWidget) {
+ super.didUpdateWidget(oldWidget);
+
+ if (widget.initialValue != oldWidget.initialValue && _isInitialized) {
+ final decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
+ final dynamic initialValue = widget.initialValue;
+ double newValue;
+
+ if (initialValue is num) {
+ newValue = initialValue.toDouble();
+ } else if (initialValue is String) {
+ newValue = double.tryParse(initialValue) ?? widget.sliderRange.$1;
+ } else {
+ newValue = widget.sliderRange.$1;
+ }
+
+ final newValueText = newValue.toStringAsFixed(decimalPlaces);
+ if (_controller.text != newValueText) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ _controller.text = newValueText;
+ _controller.selection =
+ TextSelection.collapsed(offset: _controller.text.length);
+ });
+ }
+ }
}
+
+
void _validateInput(String value) {
final doubleValue = double.tryParse(value);
if (doubleValue == null) {
@@ -121,18 +156,6 @@ class _CustomRoutinesTextboxState extends State {
}
}
- @override
- void didUpdateWidget(CustomRoutinesTextbox oldWidget) {
- super.didUpdateWidget(oldWidget);
- if (widget.initialValue != oldWidget.initialValue) {
- if (widget.initialValue != null &&
- widget.initialValue is num &&
- (widget.initialValue as num) == 0) {
- int decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
- _controller.text = 0.0.toStringAsFixed(decimalPlaces);
- }
- }
- }
void _correctAndUpdateValue(String value) {
final doubleValue = double.tryParse(value) ?? 0.0;
@@ -227,9 +250,15 @@ class _CustomRoutinesTextboxState extends State {
color: ColorsManager.blackColor,
),
keyboardType: TextInputType.number,
- inputFormatters: widget.withSpecialChar == true
- ? [FilteringTextInputFormatter.digitsOnly]
- : null,
+ inputFormatters: [
+ FilteringTextInputFormatter.allow(
+ widget.withSpecialChar
+ ? RegExp(r'^-?\d*\.?\d{0,' +
+ decimalPlaces.toString() +
+ r'}$')
+ : RegExp(r'\d+'),
+ ),
+ ],
decoration: const InputDecoration(
border: InputBorder.none,
isDense: true,
@@ -268,8 +297,9 @@ class _CustomRoutinesTextboxState extends State {
const SizedBox(height: 16),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ child: Wrap(
+ alignment: WrapAlignment.spaceBetween,
+ direction: Axis.horizontal,
children: [
Text(
'Min. ${widget.sliderRange.$1.toInt()}${widget.unit}',
@@ -279,6 +309,9 @@ class _CustomRoutinesTextboxState extends State {
fontWeight: FontWeight.w400,
),
),
+ const SizedBox(
+ width: 50,
+ ),
Text(
'Max. ${widget.sliderRange.$2.toInt()}${widget.unit}',
style: context.textTheme.bodySmall?.copyWith(
diff --git a/lib/pages/routines/widgets/if_container.dart b/lib/pages/routines/widgets/if_container.dart
index 0d7e9717..da77c7c2 100644
--- a/lib/pages/routines/widgets/if_container.dart
+++ b/lib/pages/routines/widgets/if_container.dart
@@ -78,9 +78,9 @@ class IfContainer extends StatelessWidget {
'CPS',
'NCPS',
'WH',
+ 'PC',
].contains(state.ifItems[index]
['productType'])) {
-
context.read().add(
AddToIfContainer(
state.ifItems[index], false));
@@ -137,8 +137,18 @@ class IfContainer extends StatelessWidget {
context
.read()
.add(AddToIfContainer(mutableData, false));
- } else if (!['AC', '1G', '2G', '3G', 'WPS', 'GW', 'CPS', 'NCPS','WH']
- .contains(mutableData['productType'])) {
+ } else if (![
+ 'AC',
+ '1G',
+ '2G',
+ '3G',
+ 'WPS',
+ 'GW',
+ 'CPS',
+ 'NCPS',
+ 'WH',
+ 'PC',
+ ].contains(mutableData['productType'])) {
context
.read()
.add(AddToIfContainer(mutableData, false));
diff --git a/lib/pages/routines/widgets/routine_devices.dart b/lib/pages/routines/widgets/routine_devices.dart
index 11a52ba7..f0b77467 100644
--- a/lib/pages/routines/widgets/routine_devices.dart
+++ b/lib/pages/routines/widgets/routine_devices.dart
@@ -27,6 +27,7 @@ class _RoutineDevicesState extends State {
'CPS',
'NCPS',
'WH',
+ 'PC',
};
@override
diff --git a/lib/pages/routines/widgets/routine_dialogs/ac_dialog.dart b/lib/pages/routines/widgets/routine_dialogs/ac_dialog.dart
index fc58500e..cbf13178 100644
--- a/lib/pages/routines/widgets/routine_dialogs/ac_dialog.dart
+++ b/lib/pages/routines/widgets/routine_dialogs/ac_dialog.dart
@@ -74,25 +74,24 @@ class ACHelper {
SizedBox(
width: selectedFunction != null ? 320 : 360,
child: _buildFunctionsList(
- context: context,
- acFunctions: acFunctions,
- device: device,
- onFunctionSelected:
- (functionCode, operationName) {
- RoutineTapFunctionHelper.onTapFunction(
- context,
- functionCode: functionCode,
- functionOperationName: operationName,
- functionValueDescription:
- selectedFunctionData.valueDescription,
- deviceUuid: device?.uuid,
- codesToAddIntoFunctionsWithDefaultValue: [
- 'temp_set',
- 'temp_current',
- ],
- defaultValue: 0);
- },
- ),
+ context: context,
+ acFunctions: acFunctions,
+ onFunctionSelected:
+ (functionCode, operationName) {
+ RoutineTapFunctionHelper.onTapFunction(
+ context,
+ functionCode: functionCode,
+ functionOperationName: operationName,
+ functionValueDescription:
+ selectedFunctionData
+ .valueDescription,
+ deviceUuid: device?.uuid,
+ codesToAddIntoFunctionsWithDefaultValue: [
+ 'temp_set',
+ 'temp_current',
+ ],
+ defaultValue: 0);
+ }),
),
// Value selector
if (selectedFunction != null)
@@ -150,7 +149,6 @@ class ACHelper {
required BuildContext context,
required List acFunctions,
required Function(String, String) onFunctionSelected,
- required AllDevicesModel? device,
}) {
return ListView.separated(
shrinkWrap: false,
@@ -193,7 +191,6 @@ class ACHelper {
);
}
- /// Build value selector for AC functions dialog
static Widget _buildValueSelector({
required BuildContext context,
required String selectedFunction,
@@ -207,19 +204,19 @@ class ACHelper {
acFunctions.firstWhere((f) => f.code == selectedFunction);
if (selectedFunction == 'temp_set' || selectedFunction == 'temp_current') {
- // Convert stored integer value to display value
final displayValue =
- (selectedFunctionData?.value ?? selectedFn.min ?? 0) / 10;
+ (selectedFunctionData?.value ?? selectedFn.min!) / 10;
final minValue = selectedFn.min! / 10;
final maxValue = selectedFn.max! / 10;
+
return CustomRoutinesTextbox(
withSpecialChar: true,
dividendOfRange: maxValue,
currentCondition: selectedFunctionData?.condition,
dialogType: selectedFn.type,
sliderRange: (minValue, maxValue),
- displayedValue: displayValue.toStringAsFixed(1),
- initialValue: displayValue.toDouble(),
+ displayedValue: displayValue.toString(),
+ initialValue: displayValue,
unit: selectedFn.unit!,
onConditionChanged: (condition) => context.read().add(
AddFunction(
@@ -228,7 +225,7 @@ class ACHelper {
functionCode: selectedFunction,
operationName: selectedFn.operationName,
condition: condition,
- value: 0,
+ value: (displayValue * 10).round(),
step: selectedFn.step,
unit: selectedFn.unit,
max: selectedFn.max,
@@ -236,28 +233,33 @@ class ACHelper {
),
),
),
- onTextChanged: (value) => context.read().add(
- AddFunction(
- functionData: DeviceFunctionData(
- entityId: device?.uuid ?? '',
- functionCode: selectedFunction,
- operationName: selectedFn.operationName,
- value: (value * 10).round(), // Store as integer
- condition: selectedFunctionData?.condition,
- step: selectedFn.step,
- unit: selectedFn.unit,
- max: selectedFn.max,
- min: selectedFn.min,
+ onTextChanged: (value) {
+ final numericValue = double.tryParse(value.toString()) ?? minValue;
+ context.read().add(
+ AddFunction(
+ functionData: DeviceFunctionData(
+ entityId: device?.uuid ?? '',
+ functionCode: selectedFunction,
+ operationName: selectedFn.operationName,
+ value: (numericValue * 10).round(),
+ condition: selectedFunctionData?.condition,
+ step: selectedFn.step,
+ unit: selectedFn.unit,
+ max: selectedFn.max,
+ min: selectedFn.min,
+ ),
),
- ),
- ),
- stepIncreaseAmount: selectedFn.step! / 10, // Convert step for display
+ );
+ },
+ stepIncreaseAmount: selectedFn.step! / 10,
);
}
+ // Rest of your existing code for other value selectors
+ final values = selectedFn.getOperationalValues();
return _buildOperationalValuesList(
context: context,
- values: selectedFn.getOperationalValues(),
+ values: values,
selectedValue: selectedFunctionData?.value,
device: device,
operationName: operationName,
@@ -311,7 +313,7 @@ class ACHelper {
// );
// }
- // /// Build condition toggle for AC functions dialog
+ /// Build condition toggle for AC functions dialog
// static Widget _buildConditionToggle(
// BuildContext context,
// String? currentCondition,
diff --git a/lib/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_dialog_slider_selector.dart b/lib/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_dialog_slider_selector.dart
index 3d2473c9..f26bd52a 100644
--- a/lib/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_dialog_slider_selector.dart
+++ b/lib/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_dialog_slider_selector.dart
@@ -6,7 +6,6 @@ import 'package:syncrow_web/pages/routines/models/ceiling_presence_sensor_functi
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routines/widgets/custom_routines_textbox.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_slider_helpers.dart';
-import 'package:syncrow_web/pages/routines/widgets/slider_value_selector.dart';
class CpsDialogSliderSelector extends StatelessWidget {
const CpsDialogSliderSelector({
@@ -33,7 +32,7 @@ class CpsDialogSliderSelector extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CustomRoutinesTextbox(
- withSpecialChar: false,
+ withSpecialChar: true,
currentCondition: selectedFunctionData.condition,
dialogType: dialogType,
sliderRange:
diff --git a/lib/pages/routines/widgets/routine_dialogs/power_clamp_enargy/enargy_operational_values_list.dart b/lib/pages/routines/widgets/routine_dialogs/power_clamp_enargy/enargy_operational_values_list.dart
new file mode 100644
index 00000000..2b8ba68f
--- /dev/null
+++ b/lib/pages/routines/widgets/routine_dialogs/power_clamp_enargy/enargy_operational_values_list.dart
@@ -0,0 +1,86 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
+import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
+import 'package:syncrow_web/pages/routines/models/device_functions.dart';
+import 'package:syncrow_web/pages/routines/models/pc/enrgy_clamp_operational_value.dart';
+
+class EnergyOperationalValuesList extends StatelessWidget {
+ final List values;
+ final dynamic selectedValue;
+ final AllDevicesModel? device;
+ final String operationName;
+ final String selectCode;
+
+ const EnergyOperationalValuesList({
+ required this.values,
+ required this.selectedValue,
+ required this.device,
+ required this.operationName,
+ required this.selectCode,
+ super.key,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return ListView.builder(
+ padding: const EdgeInsets.all(20),
+ itemCount: values.length,
+ itemBuilder: (context, index) => _buildValueItem(context, values[index]),
+ );
+ }
+
+ Widget _buildValueItem(
+ BuildContext context, EnergyClampOperationalValue value) {
+ return Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ _buildValueIcon(context, value),
+ Expanded(child: _buildValueDescription(value)),
+ _buildValueRadio(context, value),
+ ],
+ ),
+ );
+ }
+
+ Widget _buildValueIcon(context, EnergyClampOperationalValue value) {
+ return Column(
+ children: [
+ SvgPicture.asset(value.icon, width: 25, height: 25),
+ ],
+ );
+ }
+
+ Widget _buildValueDescription(EnergyClampOperationalValue value) {
+ return Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 8.0),
+ child: Text(value.description),
+ );
+ }
+
+ Widget _buildValueRadio(context, EnergyClampOperationalValue value) {
+ return Radio(
+ value: value.value,
+ groupValue: selectedValue,
+ onChanged: (_) => _selectValue(context, value.value),
+ );
+ }
+
+ void _selectValue(BuildContext context, dynamic value) {
+ context.read().add(
+ AddFunction(
+ functionData: DeviceFunctionData(
+ entityId: device?.uuid ?? '',
+ functionCode: selectCode,
+ operationName: operationName,
+ value: value,
+ ),
+ ),
+ );
+ }
+
+
+}
diff --git a/lib/pages/routines/widgets/routine_dialogs/power_clamp_enargy/energy_clamp_dialog.dart b/lib/pages/routines/widgets/routine_dialogs/power_clamp_enargy/energy_clamp_dialog.dart
new file mode 100644
index 00000000..c5bf8828
--- /dev/null
+++ b/lib/pages/routines/widgets/routine_dialogs/power_clamp_enargy/energy_clamp_dialog.dart
@@ -0,0 +1,246 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
+import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
+import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
+import 'package:syncrow_web/pages/routines/models/device_functions.dart';
+import 'package:syncrow_web/pages/routines/models/pc/energy_clamp_functions.dart';
+import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
+import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
+import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/helpers/routine_tap_function_helper.dart';
+import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/power_clamp_enargy/energy_value_selector_widget.dart';
+import 'package:syncrow_web/utils/color_manager.dart';
+import 'package:syncrow_web/utils/extension/build_context_x.dart';
+
+class EnergyClampDialog extends StatefulWidget {
+ final List functions;
+ final AllDevicesModel? device;
+ final List? deviceSelectedFunctions;
+ final String? uniqueCustomId;
+ final String? dialogType;
+ final bool removeComparetors;
+
+ const EnergyClampDialog({
+ super.key,
+ required this.functions,
+ this.device,
+ this.deviceSelectedFunctions,
+ this.uniqueCustomId,
+ this.dialogType,
+ this.removeComparetors = false,
+ });
+
+ static Future