自动充电任务

This commit is contained in:
cbs 2025-02-12 16:01:32 +08:00
parent 3b3d6a5e7f
commit c7b477e6ab
27 changed files with 449 additions and 66 deletions

View File

@ -35,7 +35,7 @@ public class RobotGenericsStatusApiImpl implements RobotGenericsStatusApi {
}
String mac = robotStatusData.getData().getMac();
String pose2dKey = RobotTaskChcheConstant.ROBOT_POSE_BAT +mac;
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC +mac;
Object object = redisUtil.get(pose2dKey);
RobotStatusDataPoseDTO robotStatusDataPoseDTO= JSONUtil.toBean((String)object, RobotStatusDataPoseDTO.class);

View File

@ -63,7 +63,7 @@ public class RobotStatusApiImpl implements RobotStatusApi {
String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS +robotStatusDataDTO.getMac();
String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED +robotStatusDataDTO.getMac();
String pose2dKey = RobotTaskChcheConstant.ROBOT_POSE_BAT +robotStatusDataDTO.getMac();
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC +robotStatusDataDTO.getMac();
redisUtil.set(taskStatusKey, robotStatusDataDTO.getData().getTask_status(),robotPositionCacheTime);
redisUtil.set(cargoDetectedKey,robotStatusDataDTO.getData().getCargo_detected(),robotPositionCacheTime);

View File

@ -17,7 +17,6 @@ import cn.iocoder.yudao.module.system.enums.robot.CommandTypeEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotStatusEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotTaskDetailStatusEnum;
import cn.iocoder.yudao.module.system.enums.robot.task.RobotTaksOrderTypeEnum;
import cn.iocoder.yudao.module.system.service.robot.job.RobotCommonTaskService;
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
@ -29,7 +28,6 @@ import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
@Slf4j
@RestController // 提供 RESTful API 接口 Feign 调用
@ -62,7 +60,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
return CommonResult.success(Boolean.TRUE);
}
String robotDoingActionKey = RobotTaskChcheConstant.ROBOT_DOING_ACTION +robotCompleteTaskDTO.getMac();
String robotDoingActionKey = RobotTaskChcheConstant.ROBOT_QUERY_DOING_ACTION +robotCompleteTaskDTO.getMac();
List<RobotCommandStateDTO> commandState = robotCompleteTaskDTO.getCommand_state();
if (ObjectUtil.isNotEmpty(commandState)) {
RobotCommandStateDTO robotCommandStateDTO = commandState.stream()

View File

@ -1,11 +1,17 @@
package cn.iocoder.yudao.module.system.constant.robot;
/**
* 机器人错误码
* 机器人相关信息
*/
public class RobotStatusCodeConstant {
/**
* 成功正常
*/
public static final String OK = "1000";
//货物到位传感器触发状态被按下则 true否则 false
public static Boolean CARGO_DETECTED_TRUE = true;
//IDLE RUNNING
public static String TASK_STATUS_RUNNING = "RUNNING";
}

View File

@ -2,21 +2,24 @@ package cn.iocoder.yudao.module.system.constant.robot;
public class RobotTaskChcheConstant {
//机器人能否做任务
//机器人能否做任务 (拼接的是mac地址)
public static String ROBOT_TASK_STATUS = "robot:information:task:status";
//机器人身上是否有货
//机器人身上是否有货 (拼接的是mac地址)
public static String ROBOT_CARGO_DETECTED = "robot:information:cargo:detected";
//机器人点位和电量
public static String ROBOT_POSE_BAT = "robot:information:pose2d";
//机器人点位和电量 (拼接的是mac地址)
public static String ROBOT_INFORMATION_POSE_BAT_SOC = "robot:information:pose:bat:soc";
//机器人mac地址和机器人编号映射
public static String ROBOT_NO_MAPPING_MAC = "robot:information:no:mapping:mac";
//机器人mac地址和机器人编号映射(通过mac地址查询机器人编号) (拼接的是mac地址)
public static String ROBOT_GET_ROBOTNO_BY_MAC = "robot:information:getRobotNo:ByMac";
//机器人正在做的动作
public static String ROBOT_DOING_ACTION = "robot:information:doing:action";
//机器人编号和mac地址映射(通过机器人编号查询mac地址) (拼接的是机器人编号)
public static String ROBOT_GET_MAC_BY_NO = "robot:information:getMac:ByNo";
//机器人充电模式 1:自动充电2:机会充电3:充满电
//机器人正在做的动作 (拼接的是mac地址)
public static String ROBOT_QUERY_DOING_ACTION = "robot:information:query:doing:action";
//机器人充电模式 1:自动充电2:机会充电3:充满电 (拼接的是机器人编号)
public static String ROBOT_CHARGE_MODEL = "robot:information:charge:model";
}

View File

@ -1,9 +1,11 @@
package cn.iocoder.yudao.module.system.controller.admin.config.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 参数设置
@ -24,9 +26,11 @@ public class CommonConfigVO {
private Integer chanceChargeEnd;
@Schema(description = "定时充电时段-开始时间")
@JsonFormat(pattern = "HH:mm:ss")
private LocalDateTime scheduleChargeStartTime;
@Schema(description = "定时充电时段-结束时间")
@JsonFormat(pattern = "HH:mm:ss")
private LocalDateTime scheduleChargeEndTime;
@Schema(description = "冲满电周期(天)")

View File

@ -73,4 +73,7 @@ public class DeviceInformationPageReqVO extends PageParam {
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "设备使用状态IDLE:空闲、USEING:使用中)")
private String deviceUseStatus;
}

View File

@ -90,4 +90,8 @@ public class DeviceInformationRespVO {
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "设备使用状态IDLE:空闲、USEING:使用中)")
@ExcelProperty("设备使用状态IDLE:空闲、USEING:使用中)")
private String deviceUseStatus;
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.system.controller.admin.information.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
@ -68,4 +69,7 @@ public class DeviceInformationSaveReqVO {
@Schema(description = "设备最后通讯时间")
private LocalDateTime deviceLastTime;
@Schema(description = "设备使用状态IDLE:空闲、USEING:使用中)")
private String deviceUseStatus;
}

View File

@ -24,7 +24,7 @@ public class RobotChargeLogPageReqVO extends PageParam {
@Schema(description = "结束充电电量")
private Integer endElectricity;
@Schema(description = "充电模式(1:自动充电、2:机会充电、3:充满电)")
@Schema(description = "充电模式(1:自动充电、2:机会充电、3:充满电、4:充电任务)")
private Integer chargeModel;
@Schema(description = "结束充电时间")

View File

@ -28,8 +28,8 @@ public class RobotChargeLogRespVO {
@ExcelProperty("结束充电电量")
private Integer endElectricity;
@Schema(description = "充电模式(1:自动充电、2:机会充电、3:充满电)")
@ExcelProperty("充电模式(1:自动充电、2:机会充电、3:充满电)")
@Schema(description = "充电模式(1:自动充电、2:机会充电、3:充满电、4:充电任务)")
@ExcelProperty("充电模式(1:自动充电、2:机会充电、3:充满电、4:充电任务)")
private Integer chargeModel;
@Schema(description = "结束充电时间")

View File

@ -23,7 +23,7 @@ public class RobotChargeLogSaveReqVO {
@Schema(description = "结束充电电量")
private Integer endElectricity;
@Schema(description = "充电模式(1:自动充电、2:机会充电、3:充满电)")
@Schema(description = "充电模式(1:自动充电、2:机会充电、3:充满电、4:充电任务)")
private Integer chargeModel;
@Schema(description = "结束充电时间")

View File

@ -102,5 +102,9 @@ public class DeviceInformationDO extends BaseDO {
* 设备最后通讯时间
*/
private LocalDateTime deviceLastTime;
/**
* 设备使用状态IDLE:空闲USEING:使用中
*/
private String deviceUseStatus;
}

View File

@ -27,7 +27,7 @@ public class RobotChargeLogDO extends BaseDO {
/**
* 主键ID
*/
@TableId
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* AGV编号
@ -51,7 +51,7 @@ public class RobotChargeLogDO extends BaseDO {
private String deviceNo;
/**
* 充电模式(1:自动充电2:机会充电3:充满电)
* 充电模式(1:自动充电2:机会充电3:充满电4:充电任务)
*/
private Integer chargeModel;

View File

@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.system.controller.admin.robot.chargelog.RobotChargeLogPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotChargeLogDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 车辆充电记录 Mapper
@ -28,4 +29,11 @@ public interface RobotChargeLogMapper extends BaseMapperX<RobotChargeLogDO> {
.orderByDesc(RobotChargeLogDO::getId));
}
/**
*
* @param chanceCycle
* @return
*/
List<String> getChargeFullRobotNos(@Param("chanceCycle") Integer chanceCycle,
@Param("robotNos") List<String> robotNos);
}

View File

@ -61,4 +61,11 @@ public interface RobotInformationMapper extends BaseMapperX<RobotInformationDO>
*/
void updateRobotTaskModel(@Param("robotNos") Set<String> robotNos,
@Param("robotTaskModel") Integer robotTaskModel);
/**
* 批量更新机器人状态
* @param robotNos
* @param robotStatus
*/
void updateRobotListStatus(@Param("robotNos") Set<String> robotNos, @Param("robotStatus") Integer robotStatus);
}

View File

@ -92,4 +92,10 @@ public interface RobotTaskDetailMapper extends BaseMapperX<RobotTaskDetailDO> {
*/
List<Long> getDoingTaskIds();
/**
* 获取未进行的充电任务
* @return
*/
List<RobotTaskDetailDO> getChargeTaskDetail();
}

View File

@ -10,11 +10,11 @@ public enum DeviceTypeEnum {
CHARGING_STATION(1, "充电桩"),
Conveyor_line(2, "输送线"),
PALLETIZER(3, "码垛机"),
DISMANTLING_MACHINE(4, "拆垛机"),
AUTOMATIC_DOOR(5, "自动门"),
HOIST(6, "提升机"),
SIGNAL_LIGHT(7, "信号灯"),
BUTTON_BOX(8, "按钮盒");
AUTOMATIC_DOOR(4, "自动门"),
HOIST(5, "提升机"),
SIGNAL_LIGHT(6, "信号灯"),
BUTTON_BOX(7, "按钮盒"),
DISMANTLING_MACHINE(8, "拆垛机");
/**
* 类型

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.system.enums.device;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* device_information
*/
@Getter
@AllArgsConstructor
public enum DeviceUseStatusEnum {
IDLE("IDLE", "空闲"),
USEING("USEING", "使用中");
/**
* 类型
*/
private final String type;
/**
* 说明
*/
private final String msg;
}

View File

@ -4,14 +4,15 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* robot_charge_log的charge_model 充电模式(1:自动充电2:机会充电3:充满电)
* robot_charge_log的charge_model 充电模式(1:自动充电2:机会充电3:充满电4:充电任务)
*/
@Getter
@AllArgsConstructor
public enum ChargeModelEnum {
AUTO(1), //自动充电
CHANCE(2), //机会充电
FULL(3); //充满电
FULL(3), //充满电
TASK(4); //充电任务
/**
* 类型
*/

View File

@ -47,7 +47,7 @@ public class RobotJob {
try {
distributeTasksService.distributeTasks();
} catch (Exception e) {
log.error("下发任务给车机出现异常 :{}",e.getMessage());
log.error("下发任务给车机出现异常 :{}",e);
} finally {
lock.unlock();
}
@ -70,7 +70,7 @@ public class RobotJob {
try {
robotTaskAutoMoveService.distributeAutoMoveJob();
} catch (Exception e) {
log.error("下发自动移库任务出现异常 :{}",e.getMessage());
log.error("下发自动移库任务出现异常 :{}",e);
} finally {
lock.unlock();
}
@ -80,13 +80,27 @@ public class RobotJob {
}
}
//下发自动移库任务
//下发自动充电任务
@XxlJob("AutoChargeJob")
@TenantJob
public void AutoChargeJob() {
log.info("----下发自动充电任务----");
autoChargeService.autoChargeJob();
RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_DISTRIBUTE_LOCK.getKey());
if (lock.tryLock()){
try {
log.info("----下发自动充电任务----");
autoChargeService.autoChargeJob();
} catch (Exception e) {
log.error("下发自动充电任务出现异常 :{}",e);
} finally {
lock.unlock();
}
}else {
log.info("下发自动充电任务未获取到锁");
throw exception(REDISSON_NOT_OBTAIN_LOCK);
}
}
}

View File

@ -17,7 +17,6 @@ import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskDetailMapper;
import cn.iocoder.yudao.module.system.enums.robot.*;
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
@ -106,7 +105,7 @@ public class RobotInformationServiceImpl implements RobotInformationService {
// 更新
RobotInformationDO updateObj = BeanUtils.toBean(updateReqVO, RobotInformationDO.class);
informationMapper.updateById(updateObj);
redisUtil.set(RobotTaskChcheConstant.ROBOT_NO_MAPPING_MAC + updateObj.getMacAddress(),updateObj.getRobotNo());
redisUtil.set(RobotTaskChcheConstant.ROBOT_GET_ROBOTNO_BY_MAC + updateObj.getMacAddress(),updateObj.getRobotNo());
}
@Override
@ -161,11 +160,11 @@ public class RobotInformationServiceImpl implements RobotInformationService {
* @param v
*/
private void setMsgAndRobotStatus(RobotInformationPageRespVO v) {
String pose2dKey = RobotTaskChcheConstant.ROBOT_POSE_BAT +v.getMacAddress();
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC +v.getMacAddress();
Object object = redisUtil.get(pose2dKey);
RobotStatusDataPoseDTO robotStatusDataPoseDTO= JSONUtil.toBean((String)object, RobotStatusDataPoseDTO.class);
String robotDoingActionKey = RobotTaskChcheConstant.ROBOT_DOING_ACTION +v.getMacAddress();
String robotDoingActionKey = RobotTaskChcheConstant.ROBOT_QUERY_DOING_ACTION +v.getMacAddress();
Object action = redisUtil.get(robotDoingActionKey);
if (ObjectUtil.isNotEmpty(object) && ObjectUtil.isNotEmpty(robotStatusDataPoseDTO)) {
@ -229,7 +228,7 @@ public class RobotInformationServiceImpl implements RobotInformationService {
Integer fault = 0;
//0待命1任务中2锁定3离线4:充电中5:故障
for (RobotInformationDO v : existRobot) {
String pose2dKey = RobotTaskChcheConstant.ROBOT_POSE_BAT +v.getMacAddress();
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC +v.getMacAddress();
Object object = redisUtil.get(pose2dKey);
if (ObjectUtil.isEmpty(object)) {
offline++;
@ -293,7 +292,7 @@ public class RobotInformationServiceImpl implements RobotInformationService {
if (ObjectUtil.isEmpty(mac)) {
return "";
}
String robotNo = (String) redisUtil.get(RobotTaskChcheConstant.ROBOT_NO_MAPPING_MAC + mac);
String robotNo = (String) redisUtil.get(RobotTaskChcheConstant.ROBOT_GET_ROBOTNO_BY_MAC + mac);
if (ObjectUtil.isNotEmpty(robotNo)) {
return robotNo;
@ -303,7 +302,7 @@ public class RobotInformationServiceImpl implements RobotInformationService {
.eq(RobotInformationDO::getMacAddress, mac)
.last("limit 1"));
if (ObjectUtil.isNotEmpty(robotInformationDO)) {
redisUtil.set(RobotTaskChcheConstant.ROBOT_NO_MAPPING_MAC + mac,robotInformationDO.getRobotNo());
redisUtil.set(RobotTaskChcheConstant.ROBOT_GET_ROBOTNO_BY_MAC + mac,robotInformationDO.getRobotNo());
return robotInformationDO.getRobotNo();
}
return "";

View File

@ -1,33 +1,80 @@
package cn.iocoder.yudao.module.system.service.robot.job;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO;
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
import cn.iocoder.yudao.module.system.controller.admin.config.vo.CommonConfigVO;
import cn.iocoder.yudao.module.system.dal.dataobject.config.CommonConfigDO;
import cn.iocoder.yudao.module.system.dal.dataobject.information.DeviceInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotChargeLogDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO;
import cn.iocoder.yudao.module.system.dal.mysql.config.CommonConfigMapper;
import cn.iocoder.yudao.module.system.dal.mysql.information.DeviceInformationMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotChargeLogMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotInformationMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskDetailMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskMapper;
import cn.iocoder.yudao.module.system.enums.config.CommandConfigTypeEnum;
import cn.iocoder.yudao.module.system.enums.device.DeviceTypeEnum;
import cn.iocoder.yudao.module.system.enums.device.DeviceUseStatusEnum;
import cn.iocoder.yudao.module.system.enums.robot.*;
import cn.iocoder.yudao.module.system.enums.robot.charge.ChargeModelEnum;
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import static cn.iocoder.yudao.module.system.config.SystemJobConfiguration.NOTIFY_THREAD_POOL_TASK_EXECUTOR;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Slf4j
public class AutoChargeServiceImpl implements AutoChargeService {
@Resource
private RobotInformationMapper informationMapper;
private RobotInformationMapper robotInformationMapper;
@Resource
private CommonConfigMapper configMapper;
@Resource
private RobotChargeLogMapper chargeLogMapper;
@Resource
private DeviceInformationMapper deviceInformationMapper;
@Autowired
private RobotTaskDetailMapper robotTaskDetailMapper;
@Autowired
private RobotTaskMapper robotTaskMapper;
@Resource
private RedisUtil redisUtil;
@Value("${zn.full_electricity:100}")
private String fullElectricity;
/**
* 自动充电
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void autoChargeJob() {
TenantContextHolder.setTenantId(1L);
CommonConfigDO commonConfigDO = configMapper.selectOne(new LambdaQueryWrapper<CommonConfigDO>()
.eq(CommonConfigDO::getConfigType, CommandConfigTypeEnum.ONE.getType()));
@ -36,9 +83,219 @@ public class AutoChargeServiceImpl implements AutoChargeService {
return;
}
CommonConfigVO robotStatusData = JSON.parseObject(commonConfigDO.getConfigStr() , CommonConfigVO.class);
CommonConfigVO chargeConfig= JSONUtil.toBean(commonConfigDO.getConfigStr(),CommonConfigVO.class);
List<RobotInformationDO> robots = robotInformationMapper.selectList(new LambdaQueryWrapperX<RobotInformationDO>()
.eq(RobotInformationDO::getRobotStatus, RobotStatusEnum.STAND_BY.getType())
.eq(RobotInformationDO::getRobotTaskModel, RobotTaskModelEnum.NORMAL.getType()));
if (ObjectUtil.isEmpty(robots)) {
log.info("充电任务,没有空闲机器人");
return;
}
List<DeviceInformationDO> deviceInformationDOS = deviceInformationMapper.selectList(new LambdaQueryWrapperX<DeviceInformationDO>()
.eq(DeviceInformationDO::getDeviceEnable, ZeroOneEnum.ONE.getType())
.eq(DeviceInformationDO::getDeviceUseStatus, DeviceUseStatusEnum.IDLE.getType())
.eq(DeviceInformationDO::getDeviceType, DeviceTypeEnum.CHARGING_STATION.getType()));
if (ObjectUtil.isEmpty(deviceInformationDOS)) {
log.info("充电任务,没有空闲的充电桩");
return;
}
List<String> robotNos = robots.stream()
.map(RobotInformationDO::getRobotNo)
.collect(Collectors.toList());
//近期有充满电的机器人编号
List<String> chargeFullNos = new ArrayList<>();
if (ObjectUtil.isNotEmpty(chargeConfig.getChanceCycle())) {
//查询充满电
chargeFullNos = chargeLogMapper.getChargeFullRobotNos(chargeConfig.getChanceCycle(),robotNos);
}
List<RobotTaskDetailDO> taskDetailDOS = robotTaskDetailMapper.getChargeTaskDetail();
Map<String, List<RobotTaskDetailDO>> detailMap = null;
if (ObjectUtil.isNotEmpty(taskDetailDOS)) {
detailMap = taskDetailDOS.stream().collect(Collectors.groupingBy(RobotTaskDetailDO::getRobotNo));
}
List<RobotTaskDetailDO> updateTaskDetails = new ArrayList<>();
List<RobotChargeLogDO> logs = new ArrayList<>();
Set<Long> taskIds = new HashSet<>();
//组装充电任务
assembleChargeTask(robots,deviceInformationDOS,chargeConfig,chargeFullNos,updateTaskDetails,logs,taskIds,detailMap);
if (ObjectUtil.isEmpty(logs)) {
log.info("没有需要执行的充电任务");
return;
}
if (ObjectUtil.isNotEmpty(updateTaskDetails)) {
robotTaskDetailMapper.updateBatch(updateTaskDetails);
}
if (ObjectUtil.isNotEmpty(taskIds)) {
List<RobotTaskDO> taskDOS = robotTaskMapper.selectBatchIds(taskIds);
for (RobotTaskDO taskDO : taskDOS) {
if (RobotTaskStatusEnum.NEW.getType().equals(taskDO.getTaskStatus())) {
taskDO.setTaskStatus(RobotTaskStatusEnum.DOING.getType());
taskDO.setStartTime(LocalDateTime.now());
}
}
robotTaskMapper.updateBatch(taskDOS);
}
Set<String> robotLists = logs.stream()
.map(RobotChargeLogDO::getDeviceNo)
.collect(Collectors.toSet());
if (ObjectUtil.isNotEmpty(robotLists)) {
robotInformationMapper.updateRobotListStatus(robotLists,RobotStatusEnum.DOING.getType());
}
chargeLogMapper.insertBatch(logs);
//改成异步
logs.stream().forEach(v -> {
String chargeModelKey = RobotTaskChcheConstant.ROBOT_CHARGE_MODEL +v.getRobotNo();
redisUtil.set(chargeModelKey,v.getChargeModel());
});
}
/**
* 组装充电任务
* @param robots
* @param deviceInformationDOS
* @param chargeConfig
* @param chargeFullNos
* @param updateTaskDetails
* @param logs
* @param taskIds
* @param detailMap
*/
public void assembleChargeTask(List<RobotInformationDO> robots, List<DeviceInformationDO> deviceInformationDOS,
CommonConfigVO chargeConfig, List<String> chargeFullNos, List<RobotTaskDetailDO> updateTaskDetails,
List<RobotChargeLogDO> logs, Set<Long> taskIds, Map<String, List<RobotTaskDetailDO>> detailMap) {
//判断机器人身上的电量少于设定的电量
for (RobotInformationDO robot : robots) {
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC +robot.getMacAddress();
Object poseCache = redisUtil.get(pose2dKey);
RobotStatusDataPoseDTO dataPoseDTO= JSON.parseObject((String)poseCache, RobotStatusDataPoseDTO.class);
if (ObjectUtil.isEmpty(dataPoseDTO) || ObjectUtil.isEmpty(dataPoseDTO.getBat_soc())) {
log.info("当前机器人查不到电量信息,所以不执行充电 :{}",robot.getRobotNo());
continue;
}
if (ObjectUtil.isEmpty(deviceInformationDOS)) {
log.info("充电桩分配完成 :{}",robot.getRobotNo());
break;
}
RobotChargeLogDO log = new RobotChargeLogDO();
log.setRobotNo(robot.getRobotNo());
log.setDeviceNo(deviceInformationDOS.get(0).getDeviceNo());
String[] split = dataPoseDTO.getBat_soc().split("\\.");
log.setStartElectricity(Integer.valueOf(split[0]));
//配置的充满电电量
BigDecimal robotFullElectricity = new BigDecimal(fullElectricity);
//车子剩余电量
BigDecimal robotRemainingElectricity = new BigDecimal(split[0]);
if (ObjectUtil.isNotEmpty(chargeConfig.getChanceCycle()) && !chargeFullNos.contains(robot.getRobotNo())
&& robotRemainingElectricity.compareTo(robotFullElectricity) < 0) {
//充满电
log.setChargeModel(ChargeModelEnum.FULL.getType());
logs.add(log);
deviceInformationDOS.removeIf(v -> log.getDeviceNo().equals(v.getDeviceNo()));
continue;
}
if (ObjectUtil.isNotEmpty(detailMap) && detailMap.containsKey(robot.getRobotNo())
&& ObjectUtil.isNotEmpty(robot.getAutoCharge())) {
//任务充电
BigDecimal robotConfigElectricity = new BigDecimal(String.valueOf(robot.getAutoCharge()));
if (robotRemainingElectricity.compareTo(robotConfigElectricity) < 0) {
log.setChargeModel(ChargeModelEnum.TASK.getType());
logs.add(log);
RobotTaskDetailDO robotTaskDetailDO = detailMap.get(robot.getRobotNo()).get(0);
robotTaskDetailDO.setRobotNo(robot.getRobotNo());
robotTaskDetailDO.setStartTime(LocalDateTime.now());
robotTaskDetailDO.setTaskStatus(RobotTaskDetailStatusEnum.DOING.getType());
updateTaskDetails.add(robotTaskDetailDO);
taskIds.add(robotTaskDetailDO.getRobotTaskId());
deviceInformationDOS.removeIf(v -> log.getDeviceNo().equals(v.getDeviceNo()));
continue;
}
}
if (ObjectUtil.isNotEmpty(detailMap) && detailMap.containsKey(robot.getRobotNo())
&& ObjectUtil.isEmpty(robot.getAutoCharge()) && ObjectUtil.isNotEmpty(chargeConfig.getStartAutoCharge())) {
//任务充电
BigDecimal robotConfigElectricity = new BigDecimal(String.valueOf(chargeConfig.getStartAutoCharge()));
if (robotRemainingElectricity.compareTo(robotConfigElectricity) < 0) {
log.setChargeModel(ChargeModelEnum.TASK.getType());
logs.add(log);
RobotTaskDetailDO robotTaskDetailDO = detailMap.get(robot.getRobotNo()).get(0);
robotTaskDetailDO.setRobotNo(robot.getRobotNo());
robotTaskDetailDO.setStartTime(LocalDateTime.now());
robotTaskDetailDO.setTaskStatus(RobotTaskDetailStatusEnum.DOING.getType());
updateTaskDetails.add(robotTaskDetailDO);
taskIds.add(robotTaskDetailDO.getRobotTaskId());
deviceInformationDOS.removeIf(v -> log.getDeviceNo().equals(v.getDeviceNo()));
continue;
}
}
if (ObjectUtil.isNotEmpty(detailMap) && detailMap.containsKey(robot.getRobotNo())
&& ObjectUtil.isEmpty(robot.getAutoCharge()) && ObjectUtil.isNotEmpty(chargeConfig.getChanceChargeStart())) {
//任务充电
BigDecimal robotConfigElectricity = new BigDecimal(String.valueOf(chargeConfig.getChanceChargeStart()));
if (robotRemainingElectricity.compareTo(robotConfigElectricity) < 0) {
log.setChargeModel(ChargeModelEnum.TASK.getType());
logs.add(log);
RobotTaskDetailDO robotTaskDetailDO = detailMap.get(robot.getRobotNo()).get(0);
robotTaskDetailDO.setRobotNo(robot.getRobotNo());
robotTaskDetailDO.setStartTime(LocalDateTime.now());
robotTaskDetailDO.setTaskStatus(RobotTaskDetailStatusEnum.DOING.getType());
updateTaskDetails.add(robotTaskDetailDO);
taskIds.add(robotTaskDetailDO.getRobotTaskId());
deviceInformationDOS.removeIf(v -> log.getDeviceNo().equals(v.getDeviceNo()));
continue;
}
}
if (ObjectUtil.isNotEmpty(robot.getAutoCharge())) {
//自动充电
BigDecimal robotConfigElectricity = new BigDecimal(String.valueOf(robot.getAutoCharge()));
if (robotRemainingElectricity.compareTo(robotConfigElectricity) < 0) {
log.setChargeModel(ChargeModelEnum.AUTO.getType());
logs.add(log);
deviceInformationDOS.removeIf(v -> log.getDeviceNo().equals(v.getDeviceNo()));
continue;
}
}
if (ObjectUtil.isNotEmpty(chargeConfig.getStartAutoCharge())) {
//自动充电
BigDecimal robotConfigElectricity = new BigDecimal(String.valueOf(chargeConfig.getStartAutoCharge()));
if (robotRemainingElectricity.compareTo(robotConfigElectricity) < 0) {
log.setChargeModel(ChargeModelEnum.AUTO.getType());
logs.add(log);
deviceInformationDOS.removeIf(v -> log.getDeviceNo().equals(v.getDeviceNo()));
continue;
}
}
if (ObjectUtil.isNotEmpty(chargeConfig.getChanceChargeStart())) {
//机会充电
BigDecimal robotConfigElectricity = new BigDecimal(String.valueOf(chargeConfig.getChanceChargeStart()));
if (robotRemainingElectricity.compareTo(robotConfigElectricity) < 0) {
log.setChargeModel(ChargeModelEnum.CHANCE.getType());
logs.add(log);
deviceInformationDOS.removeIf(v -> log.getDeviceNo().equals(v.getDeviceNo()));
}
}
}
}
}

View File

@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.mqtt.api.task.dto.Pose2ds;
import cn.iocoder.yudao.module.mqtt.api.task.dto.RobotAcceptTaskDTO;
import cn.iocoder.yudao.module.mqtt.api.task.dto.RobotAcceptTaskData;
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO;
import cn.iocoder.yudao.module.system.constant.robot.RobotStatusCodeConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
import cn.iocoder.yudao.module.system.controller.admin.config.vo.CommonConfigVO;
import cn.iocoder.yudao.module.system.dal.dataobject.config.CommonConfigDO;
@ -90,11 +91,6 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
@Resource
private WareHouseLocationMapper locationMapper;
//货物到位传感器触发状态被按下则 true否则 false
private static Boolean CARGO_DETECTED = true;
//IDLE RUNNING
private static String TASK_STATUS = "RUNNING";
@Resource
private RedisUtil redisUtil;
@ -129,6 +125,18 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
@Transactional(rollbackFor = Exception.class)
public Pair<List<RobotInformationDO>, List<RobotTaskDetailDO>> getRobotAndTaskDetails() {
Pair<List<RobotInformationDO>, List<RobotTaskDetailDO>> pair = Pair.of(new ArrayList<>(), new ArrayList<>());
CommonConfigDO commonConfigDO = configMapper.selectOne(new LambdaQueryWrapper<CommonConfigDO>()
.eq(CommonConfigDO::getConfigType, CommandConfigTypeEnum.ONE.getType()));
CommonConfigVO chargeConfig= JSONUtil.toBean(commonConfigDO.getConfigStr(),CommonConfigVO.class);
LocalDateTime now = LocalDateTime.now();
if ((ObjectUtil.isNotEmpty(chargeConfig.getScheduleChargeEndTime()) &&
(ObjectUtil.isNotEmpty(chargeConfig.getScheduleChargeStartTime())))
&& (now.isBefore(chargeConfig.getScheduleChargeEndTime()) && now.isAfter(chargeConfig.getScheduleChargeStartTime()))) {
log.info("充电时间,不派发任务");
return pair;
}
TenantContextHolder.setTenantId(1L);
List<RobotInformationDO> robots = robotInformationMapper.selectList(new LambdaQueryWrapperX<RobotInformationDO>()
.in(RobotInformationDO::getRobotStatus, RobotStatusEnum.STAND_BY.getType(),RobotStatusEnum.CHARGE.getType())
@ -140,20 +148,17 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
return pair;
}
CommonConfigDO commonConfigDO = configMapper.selectOne(new LambdaQueryWrapper<CommonConfigDO>()
.eq(CommonConfigDO::getConfigType, CommandConfigTypeEnum.ONE.getType()));
for (RobotInformationDO robot : robots) {
String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS +robot.getMacAddress();
String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED +robot.getMacAddress();
Object taskStatus = redisUtil.get(taskStatusKey);
if (ObjectUtil.isEmpty(taskStatus) || TASK_STATUS.equals(taskStatus.toString())) {
if (ObjectUtil.isEmpty(taskStatus) || RobotStatusCodeConstant.TASK_STATUS_RUNNING.equals(taskStatus.toString())) {
robot.setRobotStatus(RobotStatusEnum.DOING.getType());
continue;
}
Object cargoDetected = redisUtil.get(cargoDetectedKey);
if (ObjectUtil.isEmpty(cargoDetected) || CARGO_DETECTED.equals(cargoDetected)) {
if (ObjectUtil.isEmpty(cargoDetected) || RobotStatusCodeConstant.CARGO_DETECTED_TRUE.equals(cargoDetected)) {
robot.setRobotStatus(RobotStatusEnum.DOING.getType());
continue;
}
@ -200,23 +205,21 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
* @param robot
*/
private void setRobotStatus(CommonConfigDO commonConfigDO, RobotInformationDO robot) {
String pose2dKey = RobotTaskChcheConstant.ROBOT_POSE_BAT +robot.getMacAddress();
String chargeModelKey = RobotTaskChcheConstant.ROBOT_CHARGE_MODEL +robot.getMacAddress();
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC +robot.getMacAddress();
String chargeModelKey = RobotTaskChcheConstant.ROBOT_CHARGE_MODEL +robot.getRobotNo();
Object chargeModelCache = redisUtil.get(chargeModelKey);
Object poseCache = redisUtil.get(pose2dKey);
RobotStatusDataPoseDTO dataPoseDTO= JSON.parseObject((String)poseCache, RobotStatusDataPoseDTO.class);
log.info("机器人编号:{} ,信息: {}",robot.getRobotNo(),JSON.toJSONString(dataPoseDTO));
if (ObjectUtil.isEmpty(commonConfigDO) || ObjectUtil.isEmpty(pose2dKey) ) {
if (ObjectUtil.isEmpty(commonConfigDO) || ObjectUtil.isEmpty(poseCache) || ObjectUtil.isEmpty(dataPoseDTO.getBat_soc())) {
return;
}
CommonConfigVO chargeConfig= JSON.parseObject(commonConfigDO.getConfigStr(), CommonConfigVO.class);
CommonConfigVO chargeConfig=JSONUtil.toBean(commonConfigDO.getConfigStr(),CommonConfigVO.class);
//车子剩余电量
BigDecimal batSoc = new BigDecimal(dataPoseDTO.getBat_soc());
BigDecimal oneHundred = new BigDecimal("100");
BigDecimal robotRemainingElectricity = batSoc.multiply(oneHundred);
BigDecimal robotRemainingElectricity = new BigDecimal(dataPoseDTO.getBat_soc());
//设置离开的电量
BigDecimal robotEndElectricity = null;
@ -322,11 +325,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
robotTaskDetailMapper.updateBatch(updateTaskDetails);
}
if (ObjectUtil.isNotEmpty(robotNos)) {
List<RobotInformationDO> robotInformationDOS = robotInformationMapper.selectByRobotNos(robotNos);
robotInformationDOS.stream().forEach(robotInformationDO -> {
robotInformationDO.setRobotStatus(RobotStatusEnum.DOING.getType());
});
robotInformationMapper.updateBatch(robotInformationDOS);
robotInformationMapper.updateRobotListStatus(robotNos,RobotStatusEnum.DOING.getType());
}
}

View File

@ -9,4 +9,17 @@
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
<select id="getChargeFullRobotNos" resultType="java.lang.String">
select
robot_no
from robot_charge_log
where
TO_DAYS( NOW( ) ) - TO_DAYS( create_time) &lt;= #{chanceCycle}
and charge_model = '3'
and robot_no in
<foreach collection="robotNos" item="robotNo" index="index" open="(" close=")"
separator=",">
#{robotNo}
</foreach>
</select>
</mapper>

View File

@ -264,6 +264,20 @@
</foreach>
</update>
<update id="updateRobotListStatus">
update
robot_information
set
robot_status = #{robotStatus}
where
robot_no in
<foreach collection="robotNos" item="robotNo" index="index" open="(" close=")"
separator=",">
#{robotNo}
</foreach>
</update>
<!--通过主键删除-->
<delete id="deleteById">
delete

View File

@ -350,6 +350,22 @@
and deleted = '0'
</select>
<select id="getChargeTaskDetail"
resultType="cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO">
SELECT
t2.id,
t2.robot_task_id as robotTaskId,
t2.robot_no as robotNo,
t2.priority
from
robot_task t1, robot_task_detail t2
where
t1.task_status in('0','1')
and t1.id = t2.robot_task_id
and t2.task_status = '0'
and t2.task_type = '3'
</select>
<!--新增所有列-->
<insert id="insertSelect" keyProperty="id" useGeneratedKeys="true">
insert into robot_task_detail(robot_task_id, task_type, release_type, take_type, release_id, take_id,