白凤吉 2 months ago
parent
commit
b79d4290c4
  1. 11
      src/main/java/com/iflytop/gd/app/command/control/MoveToHeatAreaCommand.java
  2. 12
      src/main/java/com/iflytop/gd/app/command/control/MoveToSolutionAreaCommand.java
  3. 4
      src/main/java/com/iflytop/gd/app/command/control/TrayDownCommand.java
  4. 15
      src/main/java/com/iflytop/gd/app/controller/TestController.java
  5. 49
      src/main/java/com/iflytop/gd/app/service/device/DeviceCommandTempUtilService.java
  6. 2
      src/main/java/com/iflytop/gd/app/service/device/DeviceEmergencyStopService.java
  7. 70
      src/main/java/com/iflytop/gd/app/service/device/module/CapModuleService.java
  8. 15
      src/main/java/com/iflytop/gd/app/ws/client/DeviceEmergencyStopConfig.java

11
src/main/java/com/iflytop/gd/app/command/control/MoveToHeatAreaCommand.java

@ -80,29 +80,29 @@ public class MoveToHeatAreaCommand extends BaseCommandHandler {
return runAsync(() -> {
try {
// TrayState trayState = deviceStateService.getTrayInSolutionModule();
capModuleService.capUpBalanceNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand());//提升拍子存放区至拍子夹取的高度
gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), liquidAreaTrayPoint3D); //将机械臂移动至加液模块上方
gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawTrayPick);//将夹爪打开准备夹取托盘
gantryModuleService.gantryZMove(solutionModuleTrayMoveHeight);//下降z轴,使夹爪落入托盘孔位
gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawTrayGrip);//将夹爪收紧夹住托盘
gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴
deviceStateService.getDeviceState().getSolutionModule().setTrayStatus(0);//加液模块是否有托盘
deviceCommandTempUtilService.moveTrayHeatModuleAvoidDown(cmdDTO.getCommandId(), cmdDTO.getCommand(), null);//TODO 结构有问题临时避让 开始移动托盘之前先降下所有加热模块
// deviceCommandTempUtilService.moveTrayHeatModuleAvoidDown(cmdDTO.getCommandId(), cmdDTO.getCommand(), null);//TODO 结构有问题临时避让 开始移动托盘之前先降下所有加热模块
gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatArea4TrayClawPoint3D);//将携带托盘的机械臂移动至4号加热模块上方
gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatAreaTrayClawPoint3D);//将携带托盘的机械臂移动至加热模块上方
// deviceCommandUtilService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleId, trayLift);//抬升加热位托盘 TODO 结构有问题临时避让 屏蔽
deviceCommandTempUtilService.moveTrayHeatModuleAvoidUp(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode);//TODO 结构有问题临时避让 完毕可以升起了顺带提升目标加热模块
// deviceCommandUtilService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleId, trayLift);//抬升加热位托盘
deviceCommandTempUtilService.moveTrayHeatModuleAvoidUpNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode);Thread.sleep(3200);//TODO 结构有问题临时避让 完毕可以升起了顺带提升目标加热模块
gantryModuleService.gantryZMove(heatModuleTrayMoveHeight);//下降z轴,使托盘落入加热模块
gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawTrayPick);//将夹爪打开释放托盘
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayStatus(1);//加热模块是否存在托盘
gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴
capModuleService.capUpBalance(cmdDTO.getCommandId(), cmdDTO.getCommand());//提升拍子存放区至拍子夹取的高度
gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), capStorageCapClawPoint3D);//移动机械臂至拍子存放区上方
gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapPick);//将夹爪打开准备夹取拍子
gantryModuleService.gantryZMove(capModuleCapMoveHeight);//下降z轴,使夹爪落入拍子升降模块拍子孔位
gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapGrip);//将夹爪收紧夹住拍子
gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴
gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatAreaCapClawPointPoint3D);//将携带拍子的机械臂移动至加热模块拍子上方
capModuleService.capUpBalanceNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand()); //提升拍子存放区
gantryModuleService.gantryZMove(heatModuleCapMoveHeight);//下降z轴,使夹拍子落入加热模块
gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapPick);//将夹爪打开释放拍子
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setCapExist(true);//加热模块是否存在拍子
@ -111,7 +111,6 @@ public class MoveToHeatAreaCommand extends BaseCommandHandler {
// trayState.setInHeatModule(true);
// heatModuleService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, trayLower);//下降加热模块托盘
// deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(0);//加热模块托盘升降状态
capModuleService.capUpBalance(cmdDTO.getCommandId(), cmdDTO.getCommand()); //提升拍子存放区
gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), capStorageCapClawPoint3D);//移动机械臂至拍子存放区上方
} finally {
deviceStateService.getDeviceState().getGantryArm().setIdle(true);

12
src/main/java/com/iflytop/gd/app/command/control/MoveToSolutionAreaCommand.java

@ -84,15 +84,15 @@ public class MoveToSolutionAreaCommand extends BaseCommandHandler {
try {
// TrayState trayState = deviceStateService.getTrayInSolutionModule();
solutionModuleService.requestSolutionModule(cmdDTO.getCommandId(), cmdDTO.getCommand());//申请使用加液区并等待
capModuleService.capUpBalance(cmdDTO.getCommandId(), cmdDTO.getCommand()); //提升拍子存放区至拍子夹取的高度
capModuleService.capUpBalanceNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand()); //提升拍子存放区至拍子夹取的高度
gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatAreaCapClawPointPoint3D);//将机械臂移动至加热模块拍子上方
heatModuleService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, trayLift);//抬升指定加热位托盘
gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapPick);//将夹爪打开准备夹取拍子
gantryModuleService.gantryZMove(heatModuleCapMoveHeight);//下降z轴,使夹爪落入加热模块拍子孔位
gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapGrip);//将夹爪收紧夹住拍子
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setCapExist(false);//加热模块是否存在拍子
gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴
capModuleService.capMotorMoveByNum(-1);//拍子存放模块下降1个拍子位置
capModuleService.capMotorMoveByNumNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand(), -1);//拍子存放模块下降1个拍子位置
gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0); Thread.sleep(2000);//抬升z轴
gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), capStorageCapClawPoint3D);//将携带拍子的机械臂移动至存放区上方
gantryModuleService.gantryZMove(capModuleCapMoveHeight);//下降z轴,使夹拍子落入存放区
gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawCapPick);//将夹爪打开释放夹取的拍子
@ -105,13 +105,13 @@ public class MoveToSolutionAreaCommand extends BaseCommandHandler {
gantryModuleService.clawMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), clawTrayGrip);//将夹爪收紧夹住托盘
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayStatus(0);//加热模块是否存在托盘
// trayState.setInHeatModule(false);//托盘是否在加热模块中
gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);//抬升z轴
deviceCommandTempUtilService.moveTrayHeatModuleAvoidDownNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode);//TODO 临时避让下降
gantryModuleService.gantryZMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), 0);Thread.sleep(2500);//抬升z轴
// deviceCommandUtilService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleId, trayLower);//下降加热模块托盘
// deviceStateService.setHeatModuleStateTrayUp(heatModuleId, 0);//加热模块托盘升降状态
deviceCommandTempUtilService.moveTrayHeatModuleAvoidDown(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode);//TODO 临时避让下降
gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatArea4TrayClawPoint3D);//将携带托盘的机械臂移动至4号加热模块上方
gantryModuleService.gantryMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), liquidAreaTrayPoint3D); //将携带托盘的机械臂移动至加液模块上方
deviceCommandTempUtilService.moveTrayHeatModuleAvoidUp(cmdDTO.getCommandId(), cmdDTO.getCommand(), null, heatModuleCode);//TODO 临时避 恢复抬起状态
// deviceCommandTempUtilService.moveTrayHeatModuleAvoidUpNoWait(cmdDTO.getCommandId(), cmdDTO.getCommand(), null, heatModuleCode);//TODO 临时避 恢复抬起状态
gantryModuleService.gantryZMove(solutionModuleTrayMoveHeight);//下降z轴,使托盘落入加液模块
// trayState.setInSolutionModule(true);//托盘是否在加液模块中
deviceStateService.getDeviceState().getSolutionModule().setTrayStatus(1);//加液模块是否存在托盘

4
src/main/java/com/iflytop/gd/app/command/control/TrayDownCommand.java

@ -46,7 +46,7 @@ public class TrayDownCommand extends BaseCommandHandler {
//下降加热位托盘
heatModuleService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, trayLower);
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(0);
if (deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).getHeatingType() == HeatingType.thermostatic) {
// if (deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).getHeatingType() == HeatingType.thermostatic) {
// schedulerManager.scheduleOnce(heatModuleCode,() -> {
// try {
// heatModuleService.heaterMotorMove(cmdDTO.getCommandId(), cmdDTO.getCommand(), heatModuleCode, trayLift);
@ -55,7 +55,7 @@ public class TrayDownCommand extends BaseCommandHandler {
// log.error("加热完毕抬起托盘错误{}", heatModuleCode, e);
// }
// }, deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).getTargetTime(), TimeUnit.SECONDS);
}
// }
} catch (Exception e) {
log.error("降下托盘失败", e);
}

15
src/main/java/com/iflytop/gd/app/controller/TestController.java

@ -3,6 +3,7 @@ package com.iflytop.gd.app.controller;
import com.iflytop.gd.app.model.bo.status.CommandMutexState;
import com.iflytop.gd.app.model.dto.AllSensorDTO;
import com.iflytop.gd.app.service.api.TestService;
import com.iflytop.gd.app.service.device.DeviceEmergencyStopService;
import com.iflytop.gd.app.service.device.DeviceStateService;
import com.iflytop.gd.app.service.device.module.CapModuleService;
import com.iflytop.gd.app.service.device.module.SolutionModuleService;
@ -32,6 +33,7 @@ public class TestController {
private final CapModuleService capModuleService;
private final DeviceStateService deviceStateService;
private final SolutionModuleService solutionModuleService;
private final DeviceEmergencyStopService deviceEmergencyStopService;
@Operation(summary = "获取所有传感器读数")
@GetMapping("/all-sensor")
@ -69,4 +71,17 @@ public class TestController {
}
@Operation(summary = "触发急停")
@PostMapping("/press-emergency-stop")
public Result<?> pressEmergencyStop() throws Exception {
deviceEmergencyStopService.press();
return Result.success();
}
@Operation(summary = "解除急停")
@PostMapping("/release-emergency-stop")
public Result<?> releaseEmergencyStop() throws Exception {
deviceEmergencyStopService.release();
return Result.success();
}
}

49
src/main/java/com/iflytop/gd/app/service/device/DeviceCommandTempUtilService.java

@ -41,6 +41,27 @@ public class DeviceCommandTempUtilService {
public void moveTrayHeatModuleAvoidUp(HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception {
moveTrayHeatModuleAvoidUp(null, null, targetHeatModuleCode, exceptionHeatModuleCodes);
}
/**
* 避让抬升
* 临时移动托盘的时候加热模块升降避让
* 该方法会恢复之前升起的状态
*/
public void moveTrayHeatModuleAvoidUpNoWait(String cmdId, String cmdCode, HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception {
double trayLift = devicePositionService.getPosition(DevicePositionCode.trayLift).getDistance(); //托盘升降抬升距离
for (HeatModuleCode heatModuleCode : moveTrayHeatModuleAvoidUpStateList) {
if (!Arrays.stream(exceptionHeatModuleCodes).toList().contains(heatModuleCode)) {
DeviceCommandBundle deviceCommand = getHeaterMotorMoveDeviceCommand(heatModuleCode, trayLift);
deviceCommandService.sendCommand(cmdId, cmdCode, deviceCommand);
}
}
if (targetHeatModuleCode != null) {
DeviceCommandBundle deviceCommand = getHeaterMotorMoveDeviceCommand(targetHeatModuleCode, trayLift);
deviceCommandService.sendCommand(cmdId, cmdCode, deviceCommand);
}
for (HeatModuleCode heatModuleCode : moveTrayHeatModuleAvoidUpStateList) {
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(1);//加热模块托盘升降状态
}
}
/**
* 避让抬升
@ -82,6 +103,34 @@ public class DeviceCommandTempUtilService {
* 临时移动托盘的时候加热模块升降避让
* 该方法会下降所有升起的加热模块并且记录
*/
public void moveTrayHeatModuleAvoidDownNoWait(String cmdId, String cmdCode, HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception {
moveTrayHeatModuleAvoidUpStateList.clear();
List<HeatModuleState> heatModuleStateList = deviceStateService.getDeviceState().getHeatModule();
double trayLower = devicePositionService.getPosition(DevicePositionCode.trayLower).getDistance(); //获取加热位下降托盘位置
for (HeatModuleState heatModuleState : heatModuleStateList) {
if (!Arrays.stream(exceptionHeatModuleCodes).toList().contains(heatModuleState.getModuleCode())) {
if (heatModuleState.getTrayUp() == 1) {
HeatModuleCode heatModuleCode = heatModuleState.getModuleCode();
DeviceCommandBundle deviceCommand = getHeaterMotorMoveDeviceCommand(heatModuleCode, trayLower);
deviceCommandService.sendCommand(cmdId, cmdCode, deviceCommand);
moveTrayHeatModuleAvoidUpStateList.add(heatModuleCode);
}
}
}
if (targetHeatModuleCode != null) {
DeviceCommandBundle deviceCommand = getHeaterMotorMoveDeviceCommand(targetHeatModuleCode, trayLower);
deviceCommandService.sendCommand(cmdId, cmdCode, deviceCommand);
}
for (HeatModuleCode heatModuleCode : moveTrayHeatModuleAvoidUpStateList) {
deviceStateService.getDeviceState().getHeatModuleByCode(heatModuleCode).setTrayUp(0);//加热模块托盘升降状态
}
}
/**
* 避让下降
* 临时移动托盘的时候加热模块升降避让
* 该方法会下降所有升起的加热模块并且记录
*/
public void moveTrayHeatModuleAvoidDown(String cmdId, String cmdCode, HeatModuleCode targetHeatModuleCode, HeatModuleCode... exceptionHeatModuleCodes) throws Exception {
moveTrayHeatModuleAvoidUpStateList.clear();
List<HeatModuleState> heatModuleStateList = deviceStateService.getDeviceState().getHeatModule();

2
src/main/java/com/iflytop/gd/app/service/device/DeviceEmergencyStopService.java

@ -29,7 +29,7 @@ public class DeviceEmergencyStopService {
}
/**
* 处理解除急停
* 处理接触急停
*/
public void release(){
commandPoolManager.restartExecutor();

70
src/main/java/com/iflytop/gd/app/service/device/module/CapModuleService.java

@ -35,6 +35,60 @@ public class CapModuleService {
}
/**
* 将拍子升降区抬升至可以获取的位置 不等待
*/
public void capUpBalanceNoWait(String commandId, String command) throws Exception {
Boolean capExist01 = gdDeviceStatusService.getInputState(InputIOMId.CAP01_EXIST);
Boolean capExist02 = gdDeviceStatusService.getInputState(InputIOMId.CAP02_EXIST);
Boolean capExist03 = gdDeviceStatusService.getInputState(InputIOMId.CAP03_EXIST);
Boolean capExist04 = gdDeviceStatusService.getInputState(InputIOMId.CAP04_EXIST);
Boolean capExist05 = gdDeviceStatusService.getInputState(InputIOMId.CAP05_EXIST);
Boolean capExist06 = gdDeviceStatusService.getInputState(InputIOMId.CAP06_EXIST);
//如果传感器读数存在null则视为异常
if (capExist01 == null || capExist02 == null || capExist03 == null || capExist04 == null || capExist05 == null || capExist06 == null) {
log.error("拍子存放区获取传感器状态异常");
throw new AppException(ResultCode.SENSOR_STATUS_FAILED);
}
//先统计拍子个数
int capNum = 0;
if (capExist01) {
return;
}
if (capExist02) {
capNum++;
}
if (capExist03) {
capNum++;
}
if (capExist04) {
capNum++;
if (capExist02 && !capExist03) {
throw new AppException(ResultCode.SENSOR_STATUS_FAILED);
}
}
if (capExist05) {
capNum++;
if (capExist03 && !capExist04) {
throw new AppException(ResultCode.SENSOR_STATUS_FAILED);
}
}
if (capExist06) {
capNum++;
if (capExist04 && !capExist05) {
throw new AppException(ResultCode.SENSOR_STATUS_FAILED);
}
}
if (capNum == 0) {
throw new AppException(ResultCode.CAP_MODULE_NO_CAP);
}
double capLiftingHeight = devicePositionService.getPosition(DevicePositionCode.capLiftingHeight).getDistance();//每个拍子高度
double capLiftingHeightSum = (6 - capNum) * capLiftingHeight + 21;
//先留一个空位置不要完全抬升防止有传感器坏了的情况使用第二个传感器做校验
DeviceCommandBundle deviceCommand = DeviceCommandGenerator.capMotorMove(capLiftingHeightSum);
deviceCommandService.sendCommand(commandId, command, deviceCommand);
}
/**
* 将拍子升降区抬升至可以获取的位置
*/
public void capUpBalance(String commandId, String command) throws Exception {
@ -124,6 +178,22 @@ public class CapModuleService {
*
* @param num 1为上升1格-1为下降1格
*/
public void capMotorMoveByNumNoWait(String commandId, String command, int num) throws Exception {
double capLiftingHeight = devicePositionService.getPosition(DevicePositionCode.capLiftingHeight).getDistance();
Double capPosition = gdDeviceStatusService.getStepMotorPostion(StepMotorMId.TRAY_MOTOR_MID);
double toCapPosition = capPosition + (num * capLiftingHeight);
if (toCapPosition < 0) {
throw new AppException(ResultCode.CAP_LIFT_ERROR);
}
DeviceCommandBundle deviceCommand = DeviceCommandGenerator.capMotorMove(toCapPosition);
deviceCommandService.sendCommand(commandId, command, deviceCommand);
}
/**
* 调整拍子升降电机位置
*
* @param num 1为上升1格-1为下降1格
*/
public void capMotorMoveByNum(String commandId, String command, int num) throws Exception {
double capLiftingHeight = devicePositionService.getPosition(DevicePositionCode.capLiftingHeight).getDistance();
Double capPosition = gdDeviceStatusService.getStepMotorPostion(StepMotorMId.TRAY_MOTOR_MID);

15
src/main/java/com/iflytop/gd/app/ws/client/DeviceEmergencyStopConfig.java

@ -2,6 +2,7 @@ package com.iflytop.gd.app.ws.client;
import com.iflytop.gd.app.core.CommandPoolManager;
import com.iflytop.gd.app.service.api.CraftsService;
import com.iflytop.gd.app.service.device.DeviceEmergencyStopService;
import com.iflytop.gd.app.service.device.DeviceStateService;
import com.iflytop.gd.app.service.device.DeviceStepCommandService;
import lombok.RequiredArgsConstructor;
@ -16,10 +17,8 @@ import java.net.URI;
@Configuration
@RequiredArgsConstructor
public class DeviceEmergencyStopConfig {
private final DeviceStepCommandService stepCommandService;
private final DeviceStateService deviceStateService;
private final CommandPoolManager commandPoolManager;
private final CraftsService craftsService;
private final DeviceEmergencyStopService deviceEmergencyStopService;
@Value("${iflytophald.ip}")
String ip;
@ -34,17 +33,13 @@ public class DeviceEmergencyStopConfig {
if (s.get("event").equals("press")) {
log.info("触发急停{}", s);
try {
commandPoolManager.forceShutdownAll();//强制终止现在运行的所有指令
craftsService.stopAllCrafts();//停止所有工艺
stepCommandService.stopAll();
deviceStateService.getDeviceState().setEmergencyStop(true);
deviceEmergencyStopService.press();
} catch (Exception e) {
log.error("设备急停失败:{}", e.getMessage());
throw new RuntimeException(e);
}
} else if (s.get("event").equals("release")) {
commandPoolManager.restartExecutor();
deviceStateService.getDeviceState().setEmergencyStop(false);
deviceEmergencyStopService.release();
log.info("解除急停{}", s);
}
});

Loading…
Cancel
Save