zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/kernel/command/ShuttleCommandService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/model/PythonResult.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/LiftDispatcher.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/NavigateSolution.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/NavigateUtils.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/ShuttleDispatcher.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-asrs-wcs/src/main/resources/application.yml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/kernel/command/ShuttleCommandService.java
@@ -63,6 +63,8 @@ private BasConveyorStaService basConveyorStaService; @Autowired private ShuttleDispatcher shuttleDispatcher; @Autowired private NavigateUtils navigateUtils; // 计算 public Boolean accept(Motion motion) { @@ -519,7 +521,7 @@ //获取小车移动速度 Integer runSpeed = Optional.ofNullable(basShuttleService.getOne(new LambdaQueryWrapper<BasShuttle>().eq(BasShuttle::getDeviceId, assignCommand.getDeviceId())).getRunSpeed()).orElse(1000); Long hostId = shuttleThread.getDevice().getHostId(); List<NavigateNode> nodeList = NavigateUtils.calc(startLocNo, endLocNo, mapType, Utils.getShuttlePoints(Integer.parseInt(shuttleThread.getDevice().getDeviceNo()), Utils.getLev(startLocNo))); List<NavigateNode> nodeList = navigateUtils.calc(startLocNo, endLocNo, mapType, Utils.getShuttlePoints(Integer.parseInt(shuttleThread.getDevice().getDeviceNo()), Utils.getLev(startLocNo))); if (nodeList == null) { News.error("{} dash {} can't find navigate path!", startLocNo, endLocNo); return null; @@ -532,7 +534,7 @@ List<ShuttleCommand> commands = new ArrayList<>(); //获取分段路径 ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(nodeList); ArrayList<ArrayList<NavigateNode>> data = navigateUtils.getSectionPath(nodeList); //将每一段路径分成command指令 for (ArrayList<NavigateNode> nodes : data) { //开始路径 @@ -540,7 +542,7 @@ //目标路径 NavigateNode endPath = nodes.get(nodes.size() - 1); Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离 Integer allDistance = navigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离 //通过xy坐标小车二维码 String startCodeNum = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ(), hostId); //通过xy坐标小车二维码 @@ -575,7 +577,7 @@ //获取小车移动速度 Integer runSpeed = Optional.ofNullable(basShuttleService.getOne(new LambdaQueryWrapper<BasShuttle>().eq(BasShuttle::getDeviceId, assignCommand.getDeviceId())).getRunSpeed()).orElse(1000); Long hostId = shuttleThread.getDevice().getHostId(); List<NavigateNode> nodeList = NavigateUtils.calc(startLocNo, endLocNo, mapType, Utils.getShuttlePoints(Integer.parseInt(shuttleThread.getDevice().getDeviceNo()), Utils.getLev(startLocNo))); List<NavigateNode> nodeList = navigateUtils.calc(startLocNo, endLocNo, mapType, Utils.getShuttlePoints(Integer.parseInt(shuttleThread.getDevice().getDeviceNo()), Utils.getLev(startLocNo))); if (nodeList == null) { News.error("{} dash {} can't find navigate path!", startLocNo, endLocNo); return null; @@ -588,7 +590,7 @@ List<ShuttleCommand> commands = new ArrayList<>(); //获取分段路径 ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(nodeList); ArrayList<ArrayList<NavigateNode>> data = navigateUtils.getSectionPath(nodeList); //将每一段路径分成command指令 for (ArrayList<NavigateNode> nodes : data) { //开始路径 @@ -596,7 +598,7 @@ //目标路径 NavigateNode endPath = nodes.get(nodes.size() - 1); Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离 Integer allDistance = navigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离 //通过xy坐标小车二维码 String startCodeNum = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ(), hostId); //通过xy坐标小车二维码 zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/model/PythonResult.java
New file @@ -0,0 +1,18 @@ package com.zy.asrs.wcs.core.model; import lombok.Data; @Data public class PythonResult { private String start; private String target; private String path; private Double time; private Integer calcResult; } zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/LiftDispatcher.java
@@ -34,6 +34,8 @@ private BasLiftService basLiftService; @Autowired private ShuttleStandbyService shuttleStandbyService; @Autowired private NavigateUtils navigateUtils; /** * 根据目标位置搜索空闲提升机 @@ -80,11 +82,11 @@ } String liftLocNo = Utils.getLocNo(Utils.getRow(standby.getDeviceStandbyLoc()), Utils.getBay(standby.getDeviceStandbyLoc()), Utils.getLev(locNo)); List<NavigateNode> nodeList = NavigateUtils.calc(locNo, liftLocNo, NavigationMapType.NONE.id, null); List<NavigateNode> nodeList = navigateUtils.calc(locNo, liftLocNo, NavigationMapType.NONE.id, null); if (nodeList == null) { continue; } Integer originPathAllDistance = NavigateUtils.getOriginPathAllDistance(nodeList);//总距离 Integer originPathAllDistance = navigateUtils.getOriginPathAllDistance(nodeList);//总距离 if (originPathAllDistance < finalDistance) { finalDistance = originPathAllDistance; recentLiftThread = liftThread; zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/NavigateSolution.java
@@ -1,13 +1,18 @@ package com.zy.asrs.wcs.core.utils; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.zy.asrs.framework.common.SpringUtils; import com.zy.asrs.framework.exception.CoolException; import com.zy.asrs.wcs.core.model.NavigateNode; import com.zy.asrs.wcs.core.model.PythonResult; import com.zy.asrs.wcs.core.model.enums.MapNodeType; import com.zy.asrs.wcs.system.entity.Dict; import com.zy.asrs.wcs.system.service.DictService; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import java.util.PriorityQueue; @@ -52,45 +57,89 @@ //Exist表用来存放已经出现过的结点。 public ArrayList<NavigateNode> Exist = new ArrayList<NavigateNode>(); public NavigateNode astarSearch(NavigateNode start, NavigateNode end) { //把第一个开始的结点加入到Open表中 this.Open.add(start); //把出现过的结点加入到Exist表中 this.Exist.add(start); //主循环 while (Open.size() > 0) { //取优先队列顶部元素并且把这个元素从Open表中删除 NavigateNode current_node = Open.poll(); //将这个结点加入到Close表中 Close.add(current_node); //对当前结点进行扩展,得到一个四周结点的数组 ArrayList<NavigateNode> neighbour_node = extend_current_node(current_node); //对这个结点遍历,看是否有目标结点出现 for (NavigateNode node : neighbour_node) { // G + H + E (对启发函数增加去拐点方案calcNodeExtraCost) int gCost = calcNodeCost(current_node, node) * calcNodeExtraCost(current_node, node, end); if (node.getX() == end.getX() && node.getY() == end.getY()) {//找到目标结点就返回 //init_node操作把这个邻居结点的父节点设置为当前结点 //并且计算出G, F, H等值 node.setLastDistance(gCost); node.init_node(current_node, end); return node; } public String astarSearch(NavigateNode start, NavigateNode end, String pythonScriptPath) { String maps = JSON.toJSONString(map); String startStr = start.getX() + "-" + start.getY(); String targetStr = end.getX() + "-" + end.getY(); //进行计算对G, F, H 等值 node.setLastDistance(gCost); node.init_node(current_node, end); node.setH(calcNodeCost(node, end)); node.setF(node.getG() + node.getH()); ProcessBuilder processBuilder = new ProcessBuilder("python", pythonScriptPath, maps, startStr, targetStr); processBuilder.redirectErrorStream(true); Open.add(node); Exist.add(node); try { Process process = processBuilder.start(); // 读取Python脚本的输出 BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; StringBuilder builder = new StringBuilder(); while ((line = reader.readLine()) != null) { builder.append(line); } // 等待Python脚本执行完成 int exitCode = process.waitFor(); if (exitCode != 0) { System.out.println("Python script exited with error code: " + exitCode); return null; } reader.close(); if (builder.length() <= 0) { return null; } PythonResult result = JSON.parseObject(builder.toString(), PythonResult.class); if (result.getCalcResult() != 200) { return null; } String path = result.getPath(); return path; } catch (IOException | InterruptedException e) { e.printStackTrace(); } //如果遍历完所有出现的结点都没有找到最终的结点,返回null return null; } // public NavigateNode astarSearch(NavigateNode start, NavigateNode end) { // //把第一个开始的结点加入到Open表中 // this.Open.add(start); // //把出现过的结点加入到Exist表中 // this.Exist.add(start); // //主循环 // while (Open.size() > 0) { // //取优先队列顶部元素并且把这个元素从Open表中删除 // NavigateNode current_node = Open.poll(); // //将这个结点加入到Close表中 // Close.add(current_node); // //对当前结点进行扩展,得到一个四周结点的数组 // ArrayList<NavigateNode> neighbour_node = extend_current_node(current_node); // //对这个结点遍历,看是否有目标结点出现 // for (NavigateNode node : neighbour_node) { // // G + H + E (对启发函数增加去拐点方案calcNodeExtraCost) // int gCost = calcNodeCost(current_node, node) * calcNodeExtraCost(current_node, node, end); // if (node.getX() == end.getX() && node.getY() == end.getY()) {//找到目标结点就返回 // //init_node操作把这个邻居结点的父节点设置为当前结点 // //并且计算出G, F, H等值 // node.setLastDistance(gCost); // node.init_node(current_node, end); // return node; // } // // //进行计算对G, F, H 等值 // node.setLastDistance(gCost); // node.init_node(current_node, end); // node.setH(calcNodeCost(node, end)); // node.setF(node.getG() + node.getH()); // // Open.add(node); // Exist.add(node); // } // } // //如果遍历完所有出现的结点都没有找到最终的结点,返回null // return null; // } public ArrayList<NavigateNode> extend_current_node(NavigateNode current_node) { //默认地图母轨方向x zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/NavigateUtils.java
@@ -1,10 +1,14 @@ package com.zy.asrs.wcs.core.utils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.zy.asrs.framework.common.SpringUtils; import com.zy.asrs.wcs.core.model.MapNode; import com.zy.asrs.wcs.core.model.NavigateNode; import com.zy.asrs.wcs.core.model.enums.MapNodeType; import com.zy.asrs.wcs.core.model.enums.NavigationMapType; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collections; @@ -14,9 +18,13 @@ /** * A*算法使用工具 */ @Component public class NavigateUtils { public static List<NavigateNode> calc(String startPoint, String endPoint, Integer mapType, List<int[]> shuttlePoints) { @Value("${pythonCalcPath}") private String pythonCalcPath; public List<NavigateNode> calc(String startPoint, String endPoint, Integer mapType, List<int[]> shuttlePoints) { //通过开始编号和结束编号获取对应的xy轴坐标 int[] startArr = NavigatePositionConvert.positionToXY(startPoint);//开始节点 int[] endArr = NavigatePositionConvert.positionToXY(endPoint);//结束节点 @@ -36,36 +44,42 @@ NavigateSolution solution = new NavigateSolution(mapType, lev, whiteList, shuttlePoints); //开始节点,不纳入禁用节点内计算 NavigateNode res_node = solution.astarSearch(start, end); if (res_node == null) { String pathStr = solution.astarSearch(start, end, pythonCalcPath); if (pathStr == null) { System.err.println("未找到路径"); return null; } ArrayList<NavigateNode> list = new ArrayList<>(); //渲染 List<NavigateNode> list = new ArrayList<>(); NavigateNode fatherNode = null;//当前循环上一节点,用于拐点计算 while (res_node != null) { res_node.setDirection(null); res_node.setIsInflectionPoint(false); res_node.setZ(lev);//设置层高 JSONArray rows = JSON.parseArray(pathStr); for (int i = 0; i < rows.size(); i++) { Object currentObj = rows.get(i); NavigateNode nextNode = null; if ((i + 1) < rows.size()) { Object object = rows.get(i + 1); nextNode = pythonObjTransferNode(object, lev); } NavigateNode node = pythonObjTransferNode(currentObj, lev); //寻找拐点 HashMap<String, Object> result = searchInflectionPoint(res_node, fatherNode, res_node.getFather());//分别传入当前节点、父节点、下一节点 HashMap<String, Object> result = searchInflectionPoint(node, fatherNode, nextNode);//分别传入当前节点、父节点、下一节点 //判断当前节点是否为拐点 if (Boolean.parseBoolean(result.get("result").toString())) { //当前为拐点 res_node.setIsInflectionPoint(true); node.setIsInflectionPoint(true); //拐点方向 res_node.setDirection(result.get("direction").toString()); node.setDirection(result.get("direction").toString()); } list.add(res_node); fatherNode = res_node;//把当前节点保存成一个父节点 res_node = res_node.getFather();//迭代操作 list.add(node); fatherNode = node;//把当前节点保存成一个父节点 } Collections.reverse(list); //将每个节点里面的fatherNode至为null(方便后续计算时父节点过多导致显示的节点太多) for (NavigateNode navigateNode : list) { @@ -84,7 +98,7 @@ } //判断当前节点到下一个节点是否为拐点 public static HashMap<String,Object> searchInflectionPoint(NavigateNode currentNode, NavigateNode fatherNode, NavigateNode nextNode) { public HashMap<String,Object> searchInflectionPoint(NavigateNode currentNode, NavigateNode fatherNode, NavigateNode nextNode) { HashMap<String, Object> map = new HashMap<>(); map.put("result", false);//是否为拐点,true:拐点,false:直线 // 第一个点或直线点 @@ -103,7 +117,7 @@ /** * 计算方向 */ public static String calcDirection(NavigateNode currentNode, NavigateNode fatherNode) { public String calcDirection(NavigateNode currentNode, NavigateNode fatherNode) { //拐点方向 String direction = ""; // 普通拐点 @@ -139,7 +153,7 @@ * 加转弯节点 * 获取分段路径,每当有一个拐点则进行一次分段,最终返回总分段数据 */ public static ArrayList<ArrayList<NavigateNode>> getSectionPath(List<NavigateNode> mapList) { public ArrayList<ArrayList<NavigateNode>> getSectionPath(List<NavigateNode> mapList) { ArrayList<ArrayList<NavigateNode>> list = new ArrayList<>(); ArrayList<NavigateNode> data = new ArrayList<>(); @@ -169,7 +183,7 @@ } //获取从x点到下一点的行走距离 public static Integer getXToNextDistance(NavigateNode xNode) { public Integer getXToNextDistance(NavigateNode xNode) { NavigateMapData mapData = SpringUtils.getBean(NavigateMapData.class); mapData.setLev(xNode.getZ()); List<List<MapNode>> lists = mapData.getJsonData(NavigationMapType.NONE.id, null, null); @@ -195,11 +209,11 @@ /** * 根据原始节点结果,计算总行走距离 */ public static Integer getOriginPathAllDistance(List<NavigateNode> path) { ArrayList<ArrayList<NavigateNode>> sectionPath = NavigateUtils.getSectionPath(path); public Integer getOriginPathAllDistance(List<NavigateNode> path) { ArrayList<ArrayList<NavigateNode>> sectionPath = getSectionPath(path); Integer allDistance = 0; for (ArrayList<NavigateNode> navigateNodes : sectionPath) { Integer distance = NavigateUtils.getCurrentPathAllDistance(navigateNodes); Integer distance = getCurrentPathAllDistance(navigateNodes); allDistance += distance; } return allDistance; @@ -208,7 +222,7 @@ /** * 获取当前路径总行走距离 */ public static Integer getCurrentPathAllDistance(List<NavigateNode> path) { public Integer getCurrentPathAllDistance(List<NavigateNode> path) { if (path.size() == 1) { //路径只有一条数据,则直接返回行走距离 return path.get(0).getMoveDistance(); @@ -225,7 +239,7 @@ /** * 获取中间点到目标点行走距离 */ public static Integer getMiddleToDistDistance(List<NavigateNode> path, NavigateNode middlePath) { public Integer getMiddleToDistDistance(List<NavigateNode> path, NavigateNode middlePath) { //最后一条节点不计算进行走距离 NavigateNode lastPath = path.get(path.size() - 1); //总距离 @@ -250,7 +264,7 @@ /** * 检测路径是否可用(可走) */ public static boolean checkPathIsAvailable(List<NavigateNode> path, Integer shuttleNo, Integer lev) { public boolean checkPathIsAvailable(List<NavigateNode> path, Integer shuttleNo, Integer lev) { NavigateSolution solution = new NavigateSolution(NavigationMapType.DFX.id, lev, null, Utils.getShuttlePoints(shuttleNo, lev));//获取无白名单地图(该地图包含小车坐标) int[][] map = solution.map; for (NavigateNode node : path) { @@ -262,20 +276,32 @@ return true; } public static void main(String[] args) { //计算路径 List<NavigateNode> calc = calc("1000901", "1800201", NavigationMapType.NONE.id, null); System.out.println(calc); System.out.println("------------------------"); // List<NavigateNode> calc = calc("0501401", "0201801", "out"); //将路径分割成多段 ArrayList<ArrayList<NavigateNode>> data = getSectionPath(calc); for (ArrayList<NavigateNode> list : data) { Integer currentPathAllDistance = getCurrentPathAllDistance(list);//计算当前路径总距离 System.out.println(currentPathAllDistance); System.out.println(list); } private NavigateNode pythonObjTransferNode(Object obj, Integer z) { List<Integer> pathData = JSON.parseArray(obj.toString(), Integer.class); Integer x = pathData.get(0); Integer y = pathData.get(1); NavigateNode node = new NavigateNode(x, y); node.setDirection(null); node.setIsInflectionPoint(false); node.setZ(z); return node; } // public static void main(String[] args) { // //计算路径 // List<NavigateNode> calc = calc("1000901", "1800201", NavigationMapType.NONE.id, null); // System.out.println(calc); // System.out.println("------------------------"); //// List<NavigateNode> calc = calc("0501401", "0201801", "out"); // //将路径分割成多段 // ArrayList<ArrayList<NavigateNode>> data = getSectionPath(calc); // for (ArrayList<NavigateNode> list : data) { // Integer currentPathAllDistance = getCurrentPathAllDistance(list);//计算当前路径总距离 // System.out.println(currentPathAllDistance); // System.out.println(list); // } // // } } zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/utils/ShuttleDispatcher.java
@@ -56,6 +56,8 @@ private ShuttleStandbyService shuttleStandbyService; @Autowired private DictService dictService; @Autowired private NavigateUtils navigateUtils; public synchronized ShuttleThread searchIdleShuttle(Task task) { String locNo = taskService.judgeInbound(task) ? task.getDestLoc() : task.getOriginLoc(); @@ -144,7 +146,7 @@ // 同楼层直接计算到目标库位 //当前穿梭车线程到当前车子所在楼层的目标库位距离 List<NavigateNode> currentShuttlePath = NavigateUtils.calc( List<NavigateNode> currentShuttlePath = navigateUtils.calc( currentLocNo , locNo , NavigationMapType.NORMAL.id @@ -154,7 +156,7 @@ continue; } Integer currDistance = NavigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 Integer currDistance = navigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 // 挂载任务权重 List<Task> tasks = taskService.selectWorkingByShuttle(Integer.valueOf(device.getDeviceNo()), null); @@ -238,7 +240,7 @@ String targetLocNo = shuttleStandby.getDeviceLoc(); //当前穿梭车线程到当前车子所在楼层的提升机待机位距离 List<NavigateNode> currentShuttlePath = NavigateUtils.calc( List<NavigateNode> currentShuttlePath = navigateUtils.calc( currentLocNo , targetLocNo , NavigationMapType.NORMAL.id @@ -248,7 +250,7 @@ continue; } Integer currDistance = NavigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 Integer currDistance = navigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 // 不同楼层权重 if (currentLev != Utils.getLev(locNo)) { @@ -401,7 +403,7 @@ String recentLoc = null; for (String loc : locNos) { //当前穿梭车到避让位计算 List<NavigateNode> currentShuttlePath = NavigateUtils.calc( List<NavigateNode> currentShuttlePath = navigateUtils.calc( currentLocNo , loc , NavigationMapType.NORMAL.id @@ -411,7 +413,7 @@ continue; } Integer currDistance = NavigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 Integer currDistance = navigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 if (currDistance < finalDistance) { finalDistance = currDistance; recentLoc = loc; @@ -521,13 +523,13 @@ //分析出库路径待机库位 public String analyzeOutPathWaitLoc(String startLoc, String targetLoc, Device shuttleDevice) { //计算路径并分解成两段动作 List<NavigateNode> nodeList = NavigateUtils.calc(startLoc, targetLoc, NavigationMapType.DFX.id, Utils.getShuttlePoints(Integer.parseInt(shuttleDevice.getDeviceNo()), Utils.getLev(startLoc))); List<NavigateNode> nodeList = navigateUtils.calc(startLoc, targetLoc, NavigationMapType.DFX.id, Utils.getShuttlePoints(Integer.parseInt(shuttleDevice.getDeviceNo()), Utils.getLev(startLoc))); if (nodeList == null) { News.error("{} dash {} can't find navigate path!", startLoc, targetLoc); return null; } //获取分段路径 ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(nodeList); ArrayList<ArrayList<NavigateNode>> data = navigateUtils.getSectionPath(nodeList); if (data.size() <= 1) { return startLoc;//两点之间只有一段路径,在起点位置等待 } zy-asrs-wcs/src/main/resources/application.yml
@@ -61,4 +61,6 @@ pwd: xltys1995 config: token-key: KUHSMcYQ4lePt3r6bckz0P13cBJyoonYqInThvQlUnbsFCIcCcZZAbWZ6UNFztYNYPhGdy6eyb8WdIz8FU2Cz396TyTJk3NI2rtXMHBOehRb4WWJ4MdYVVg2oWPyqRQ2 token-key: KUHSMcYQ4lePt3r6bckz0P13cBJyoonYqInThvQlUnbsFCIcCcZZAbWZ6UNFztYNYPhGdy6eyb8WdIz8FU2Cz396TyTJk3NI2rtXMHBOehRb4WWJ4MdYVVg2oWPyqRQ2 pythonCalcPath: D://cpu.py