Enhance MACHINE relay control logic and add emergency override functionality
- Add `forceTurnOffMachineRelay` method for superuser/emergency operations to bypass gating restrictions. - Enforce `toggle_after = 0` to prevent auto-toggle behavior. - Update routes to explicitly reflect relay state when modifying MACHINE relay. - Extend Shelly device switch handling with optional `skip_toggle_after` parameter.
This commit is contained in:
@@ -17,4 +17,9 @@ enum selfserve_lane_state
|
|||||||
case FAULT; // The lane is in a fault state
|
case FAULT; // The lane is in a fault state
|
||||||
case MAINTENANCE; // The lane is under maintenance
|
case MAINTENANCE; // The lane is under maintenance
|
||||||
case CLOSED; // The lane is closed
|
case CLOSED; // The lane is closed
|
||||||
|
|
||||||
|
public function equals(selfserve_lane_state $state): bool
|
||||||
|
{
|
||||||
|
return $this === $state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ trait selfserve_lane_relay_controller_t
|
|||||||
}, $result);
|
}, $result);
|
||||||
// Turn on the switch
|
// Turn on the switch
|
||||||
foreach ($result as $device) {
|
foreach ($result as $device) {
|
||||||
if ($duration !== null) $device->toggle_after = $duration; // Set the duration to turn off the relay (if specified)
|
// Ensure machine switches never auto-toggle off; enforce toggle_after = 0
|
||||||
|
$device->toggle_after = 0;
|
||||||
$device->switch(true);
|
$device->switch(true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -103,12 +104,52 @@ trait selfserve_lane_relay_controller_t
|
|||||||
}, $result);
|
}, $result);
|
||||||
// Turn on the switch
|
// Turn on the switch
|
||||||
foreach ($result as $device) {
|
foreach ($result as $device) {
|
||||||
if ($duration !== null) $device->toggle_after = $duration;
|
// Ensure machine switches never auto-toggle off; enforce toggle_after = 0
|
||||||
|
$device->toggle_after = 0;
|
||||||
$device->switch(true);
|
$device->switch(true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force turn off the MACHINE relay, bypassing allowed services gating.
|
||||||
|
* Intended for superuser/emergency operations.
|
||||||
|
* @return bool
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function forceTurnOffMachineRelay(): bool
|
||||||
|
{
|
||||||
|
// Require department lane object
|
||||||
|
if (empty($this->department_lane)) throw new \Exception("Department lane object not found for lane ID {$this->id}");
|
||||||
|
// Basic sanity checks on lane status (still disallow clearly invalid states)
|
||||||
|
if ($this->getLaneStatus()->equals(selfserve_lane_status::CLOSED)) throw new \Exception("Cannot turn off relay on CLOSED lane");
|
||||||
|
if ($this->getLaneStatus()->equals(selfserve_lane_status::MAINTENANCE)) throw new \Exception("Cannot turn off relay on MAINTENANCE lane");
|
||||||
|
if ($this->getLaneStatus()->equals(selfserve_lane_status::FAULT)) throw new \Exception("Cannot turn off relay on FAULT lane");
|
||||||
|
// Directly control Shelly without checking allowed services
|
||||||
|
$relay_id = $this->department_lane->relay_machine_id->value();
|
||||||
|
if (empty($relay_id)) {
|
||||||
|
throw new \Exception("Invalid relay ID for MACHINE relay");
|
||||||
|
}
|
||||||
|
$shelly = new shelly();
|
||||||
|
$shelly->requireModuleEnabled();
|
||||||
|
$shelly->requireValidSecretKey();
|
||||||
|
$parameters = new shelly_request_body_get_states();
|
||||||
|
$parameters->ids = [$relay_id];
|
||||||
|
$parameters->select = ['status'];
|
||||||
|
$result = $shelly->sendPostRequest('/v2/devices/api/get', (array)$parameters);
|
||||||
|
// Wait 1 second
|
||||||
|
sleep(1);
|
||||||
|
// Format the result
|
||||||
|
$result = array_map(function ($device) {
|
||||||
|
return (new shelly_device_switch())->populate($device);
|
||||||
|
}, $result);
|
||||||
|
// Turn off the switch
|
||||||
|
foreach ($result as $device) {
|
||||||
|
$device->switch(false);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn off the lane relay
|
* Turn off the lane relay
|
||||||
* @param selfserve_lane_relay $relay The relay to turn off (MACHINE)
|
* @param selfserve_lane_relay $relay The relay to turn off (MACHINE)
|
||||||
|
|||||||
@@ -35,16 +35,17 @@ class shelly_device_switch extends shelly_device_state
|
|||||||
/**
|
/**
|
||||||
* Send a request to the shelly API to switch the output
|
* Send a request to the shelly API to switch the output
|
||||||
* @param bool $on
|
* @param bool $on
|
||||||
|
* @param bool|null $skip_toggle_after Whether to prevent the toggle_after parameter from being sent (if null, will use the value of $this->toggle_after)
|
||||||
* @return array|object|null
|
* @return array|object|null
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function switch(bool $on): array|object|null
|
public function switch(bool $on, ?bool $skip_toggle_after = false): array|object|null
|
||||||
{
|
{
|
||||||
$parameters = [
|
$parameters = [
|
||||||
'id' => (string)$this->id,
|
'id' => (string)$this->id,
|
||||||
'channel' => (int)$this->channel,
|
'channel' => (int)$this->channel,
|
||||||
'on' => $on,
|
'on' => $on,
|
||||||
'toggle_after' => (int)$this->toggle_after,
|
'toggle_after' => $skip_toggle_after ? 0 : (int)$this->toggle_after,
|
||||||
];
|
];
|
||||||
return (new shelly())->sendPostRequest('/v2/devices/api/set/switch', $parameters);
|
return (new shelly())->sendPostRequest('/v2/devices/api/set/switch', $parameters);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,6 +241,8 @@ class moduleSelfServeRoute
|
|||||||
}
|
}
|
||||||
// Force enable the machine relay (bypass gating)
|
// Force enable the machine relay (bypass gating)
|
||||||
$lane->forceTurnOnMachineRelay($duration);
|
$lane->forceTurnOnMachineRelay($duration);
|
||||||
|
// Reflect relay state explicitly
|
||||||
|
try { $lane->setLaneState(\modules\selfserve\helpers\selfserve_lane_state::MACHINE_RELAY_ON); } catch (\Throwable $ignored) {}
|
||||||
$response->success([
|
$response->success([
|
||||||
'lane_id' => $lane_id,
|
'lane_id' => $lane_id,
|
||||||
'forced' => true,
|
'forced' => true,
|
||||||
@@ -283,8 +285,10 @@ class moduleSelfServeRoute
|
|||||||
if ((int)$lane->getWashStartTime() <= 0) {
|
if ((int)$lane->getWashStartTime() <= 0) {
|
||||||
$lane->setWashStartTime(time());
|
$lane->setWashStartTime(time());
|
||||||
}
|
}
|
||||||
// Turn off the machine relay if currently on
|
// Turn off the machine relay (do not swallow errors)
|
||||||
try { $lane->turnOffRelay(\modules\selfserve\helpers\selfserve_lane_relay::MACHINE); } catch (\Throwable $ignored) {}
|
$lane->forceTurnOffMachineRelay();
|
||||||
|
// Reflect relay state explicitly
|
||||||
|
try { $lane->setLaneState(\modules\selfserve\helpers\selfserve_lane_state::MACHINE_RELAY_OFF); } catch (\Throwable $ignored) {}
|
||||||
$response->success([
|
$response->success([
|
||||||
'lane_id' => $lane_id,
|
'lane_id' => $lane_id,
|
||||||
'forced' => true,
|
'forced' => true,
|
||||||
|
|||||||
Reference in New Issue
Block a user