import * as THREE from 'three' import { ObjectAlarmCommand } from './ObjectAlarmCommand.js' import * as TWEEN from 'three/examples/jsm/libs/tween.module.js' const WebsocketMessageReceive = function(editor) { const scope = this this.websocketMessage = (msg) => { new Promise((resolve, reject) => { let returnMes const arrays_signal = msg.data.split('|') const m_SourceType = arrays_signal[0] // 数据类型:DT:数字孪生数据 const m_DeviceType = arrays_signal[1] // 设备类型,Robot:机器人类型的设备,Device:普通设备 const m_DeviceName = arrays_signal[2] // 设备名称 const m_DevicePartName = arrays_signal[3] // 设备运动部件 const m_DevicePartDate = arrays_signal[4] // 设备运动部件数据 switch (m_SourceType) { case 'DT': switch (m_DeviceType) { case editor.ProtocolIdentifiers.Robot_7: // 接受机器人运动数据进行播放 --------------------------现场用---------------- returnMes = scope.deviceMoveEvent.RobotTranslation7(m_DeviceName, m_DevicePartName, m_DevicePartDate) break case editor.ProtocolIdentifiers.Device_3: console.log('设备运行')// --------------------------现场用---------------- returnMes = scope.deviceMoveEvent.DeviceThreeAxis(m_DeviceName, m_DevicePartName, m_DevicePartDate) break case editor.ProtocolIdentifiers.Agv_3:// --------------------------现场用---------------- console.log('AGV运行') returnMes = scope.deviceMoveEvent.AGVThreeAxis(m_DeviceName, m_DevicePartName, m_DevicePartDate) break case editor.ProtocolIdentifiers.Device_1: // 接受设备运动数据进行播放,已更新 break case editor.ProtocolIdentifiers.FirstPosition: // 接受第一个点的数据,瞬间跳到该点,已更新 break case editor.ProtocolIdentifiers.WareHousePart: // returnMes = scope.drawWareHousePartOne(m_DeviceName) break case editor.ProtocolIdentifiers.Robot_6: // 接受机器人运动数据进行播放 returnMes = scope.deviceMoveEvent.RobotTranslation(m_DeviceName, m_DevicePartName, m_DevicePartDate) break case editor.ProtocolIdentifiers.ReLoadData: // 加载所有要播放的数据,避免资源浪费 ***********************UUID测试好用了****************************** break case editor.ProtocolIdentifiers.PlayAct: // 根据ID 播放数据 状态为1 0暂停 ***********************UUID测试好用了****************************** scope.playActData(m_DeviceName, parseInt(m_DevicePartName)) break // case editor.ProtocolIdentifiers.ModelTransparent: // 根据传过来的模型名字和透明度 改变模型的透明度 ***********************UUID测试好用了****************************** // returnMes = scope.robotPlan_ModelOperation.modelTrans(m_DeviceName, m_DevicePartName) // break case editor.ProtocolIdentifiers.Visible: // 接受CS指令显示、隐藏模型 ***********************UUID测试好用了****************************** returnMes = scope.visibleObjectToBS(m_DeviceName, m_DevicePartName) break case 'JointMoveTo': if (!JSON.parse(m_DevicePartName)) console.log('JointMoveTo数据不对' + m_DevicePartName) this.JointMoveTo(m_DeviceName, JSON.parse(m_DevicePartName)) break case editor.ProtocolIdentifiers.C_B_TagIDTrigger: { const tag = JSON.parse(m_DeviceName) scope.solveTagValue(tag.TagID, tag.TagValue) } break case editor.ProtocolIdentifiers.C_B_ObjectAlarm: { const Info = JSON.parse(m_DeviceName) console.log(Info) for (const infoElement of Info) { new ObjectAlarmCommand(editor, infoElement.ModelId).exec(!!parseInt(infoElement.value)) } } break case editor.ProtocolIdentifiers.C_B_JointMoveTo: { const MoveValueList = JSON.parse(m_DeviceName) scope.ModelJointMoveTo(MoveValueList) } break case 'showWeld': this.showWeld(m_DeviceName, m_DevicePartName) break case 'showCheckOk': this.showCheckOk(m_DeviceName, m_DevicePartName) break default: returnMes = '不存在协议:' + msg break } break default: returnMes = '不存在协议:' + msg break } resolve(returnMes) }) } /** * HandlerType: 1:显隐,2:自转,3:行为,4:私服位置,5:附加拆离指令 * HandlerCode: 模型或者工艺代码 * HandlerValue: 显隐:0/1 ,自传:正负转速&axis,行为暂停播放:0/1 * TagValueTagValue: 信号值 * @param tagId * @param tagValue */ this.solveTagValue = (tagId, tagValue) => { const scope = this const actionInfo = editor.TagActList[tagId] if (!actionInfo) return for (const actionInfoElement of actionInfo) { switch (actionInfoElement.HandlerType) { case editor.signalSolveType.warning: // 报警 if (tagValue === actionInfoElement.TagValue) { new ObjectAlarmCommand(editor, actionInfoElement.HandlerCode).exec(!!parseInt(actionInfoElement.HandlerValue)) } break case editor.signalSolveType.visible: // 显隐 if (tagValue === actionInfoElement.TagValue) { scope.visibleObjectToBS(actionInfoElement.HandlerCode, parseInt(actionInfoElement.HandlerValue)) } break case editor.signalSolveType.rotation: // 自转 if (tagValue === actionInfoElement.TagValue) { const ValueFactor = actionInfoElement.ValueFactor const Axis = actionInfoElement.Axis // const JointType = actionInfoElement.JointType const Flip = actionInfoElement.Flip const ModelCode = actionInfoElement.HandlerCode scope.modelRotation(ModelCode, Axis, Flip * parseFloat(ValueFactor)) } break case editor.signalSolveType.craft: // 行为 if (tagValue === actionInfoElement.TagValue) { scope.playActData(actionInfoElement.HandlerCode, parseInt(actionInfoElement.HandlerValue)) } break case editor.signalSolveType.targetLocation: // 伺服位置 scope.solveServoSignal(actionInfoElement, tagValue) break case editor.signalSolveType.attach: // 附加功能 console.log('这个地方的附加功能没用写') break default: break } } } /** * 根据ACTid播放动作,开启线程 * @param actID * @param state */ this.playActData = (actID, state) => { const scope = this if (!editor.isOk) return if (!editor.worker[actID]) editor.worker[actID] = new Worker('./DMT_WEB/webWorker/playFunction.js') if (editor.moveTrigger[actID].moveStatus !== state) { editor.worker[actID].postMessage({ ActID: actID, State: state, isOk: editor.isOk, craftPlaySolveType: editor.craftPlaySolveType, moveTrigger: JSON.stringify(editor.moveTrigger[actID]) }) editor.moveTrigger[actID].moveStatus = state } editor.worker[actID].onmessage = function(event) { editor.moveTrigger[actID].myVarSetInterval = event.data.myVarSetInterval editor.moveTrigger[actID].currentFrame = event.data.pausedFrame const currentFrameData = event.data.currentFrameData const frameType = event.data.frameType editor.solveAttachModel('', true) switch (frameType) { case editor.craftPlaySolveType.attach: if (editor.FrameOperation.attach) { const position = currentFrameData['AttachToModelCode'] const List_AttachModel = currentFrameData['List_AttachModel'] const IsTwoWay = currentFrameData['IsTwoWay'] const IsAttach = currentFrameData['IsAttach'] if (IsAttach) { const attachData = [] for (const editorElement of List_AttachModel) { attachData.push({ ModelId: editorElement.ModelCode, ModelName: editorElement.ModelName, RootId: position, IsTwoWay: IsTwoWay }) } editor.attachList.set(position, attachData) } else { for (const detachData of List_AttachModel) { const detachModelCode = detachData.ModelCode editor.scene.attach(editor.getObjectById(detachModelCode)) editor.attachList.forEach((value, key) => { const attachList = value.filter(res => { return res.ModelId !== detachModelCode }) editor.attachList.set(key, attachList) }) } } } break case editor.craftPlaySolveType.visible: if (editor.FrameOperation.visibleObject) { const position = currentFrameData['ModelCode'] const Visible = parseInt(currentFrameData['Visible']) scope.visibleObjectToBS(position, Visible) } break case editor.craftPlaySolveType.rotation: if (editor.FrameOperation.rotationObject) { const position = currentFrameData['ModelCode'] const Axis = currentFrameData['Axis'] const Rate = currentFrameData['Rate'] scope.modelRotation(position, Axis, Rate) } break case editor.craftPlaySolveType.craft: if (editor.FrameOperation.playCraft) { const position = currentFrameData['CraftCode'] const craftState = parseInt(currentFrameData['CraftValue']) scope.playActData(position, craftState) } break case editor.craftPlaySolveType.FrameData: { const position = currentFrameData['i'] const objectToMove = editor.getObjectById(position) if (objectToMove) { if (currentFrameData.tx === 'NaN' || currentFrameData.ty === 'NaN' || currentFrameData.tz === 'NaN' || currentFrameData.qx === 'NaN' || currentFrameData.qy === 'NaN' || currentFrameData.qz === 'NaN' || currentFrameData.qw === 'NaN') { console.log('craftDataError') // editor.robotPlan_MessageList.execute(position, 'craftDataError') } else { const movePosition = new THREE.Vector3(parseFloat(currentFrameData.tx), parseFloat(currentFrameData.ty), parseFloat(currentFrameData.tz)) const nq = new THREE.Quaternion(parseFloat(currentFrameData.qx), parseFloat(currentFrameData.qy), parseFloat(currentFrameData.qz), parseFloat(currentFrameData.qw)) objectToMove.quaternion.copy(nq) objectToMove.position.copy(movePosition) } } } break case editor.craftPlaySolveType.warning: // 报警 if (editor.FrameOperation.warning) { new ObjectAlarmCommand(scope.editor, currentFrameData['ModelCode']).exec(!!parseInt(currentFrameData['Visible'])) } break default: delete editor.worker[event.data.ActID] editor.moveTrigger[actID].moveStatus = 0 editor.moveTrigger[actID].myVarSetInterval = null editor.moveTrigger[actID].currentFrame = 0 editor.moveTrigger[actID].pausedFrame = 0 break } editor.solveAttachModel('', false) } } /** * 接受CS模型自转的指令 * 接受CS模型自转的指令 * @param objectNames * @param values * @param axis */ this.modelRotation = (objectNames, axis, values) => { const scope = this const EP = 0.000001 let dir = 0 if (!editor.getObjectById(objectNames)) return const currentModel = editor.getObjectById(objectNames) if ((parseFloat(values) >= -EP) && (parseFloat(values) <= EP)) { if (editor.RotationWorker[objectNames]) { editor.RotationWorker[objectNames].terminate() delete editor.RotationWorker[objectNames] delete editor.ModelRotateWorker[objectNames] } return } else { dir = 1 if (editor.RotationWorker[objectNames]) { editor.RotationWorker[objectNames].terminate() delete editor.RotationWorker[objectNames] delete editor.ModelRotateWorker[objectNames] } } editor.RotationWorker[objectNames] = new Worker('webWorker/modelRotation.js') if (!editor.ModelRotateWorker[objectNames]) { editor.ModelRotateWorker[objectNames] = { state: 0, myVarSetInterval: null, doAnimation: false, ModelCode: objectNames } } editor.RotationWorker[objectNames].postMessage({ ObjectNames: objectNames, Values: values, Dir: dir, ModelRotateWorker: editor.ModelRotateWorker[objectNames], RotateSpeed: editor.rotateSpeed, RotationValue: currentModel.rotation[axis] }) editor.RotationWorker[objectNames].onmessage = (event) => { scope.modelSelfRotation(currentModel, event.data.rotation, axis) } } this.modelSelfRotation = (currentModel, rotation, axis) => { currentModel.rotation[axis] = rotation } this.ModelJointMoveTo = (MoveValueList) => { // TOBS?WEB?SCADAMain?DT|C_B_JointMoveTo|[{"ModelCode":"5E6D91B8-B44D-4C44-AAEF-10492E548A1A","JointType":"rotation","Axis":"x","Flip":1,"Value":0,"ValueFactor":0.017453292519943295,"Delta":0}] // TOBS?WEB?SCADAMain?DT|C_B_JointMoveTo|[{"ModelCode":"644506B1-A05A-4E57-BBA2-C63635586C63","JointType":"position","Axis":"y","Flip":-1,"Value":-15.0,"ValueFactor":0.001,"Delta":-655.0}] new Promise(resolve => { for (const MoveValue of MoveValueList) { const ModelCode = MoveValue.ModelCode const ValueFactor = parseFloat(MoveValue.ValueFactor) const type = MoveValue.JointType const Value = parseFloat(MoveValue.Value) const Flip = parseFloat(MoveValue.Flip) const axis = MoveValue.Axis const Delta = parseFloat(MoveValue.Delta) const object = editor.getObjectById(ModelCode) const originInfo = editor.objectIdSet.get(ModelCode) if (!originInfo) return const matrix = originInfo['matrix'] const originValue = type === 'rotation' ? originInfo[type]['_' + axis] : originInfo[type][axis] const lastValue = originInfo['lastValue'] === null ? originValue : originInfo['lastValue'] const moveValue = Flip * (Value - Delta) * ValueFactor if (object) { editor.solveAttachModel('', true) const JointValue = originValue + moveValue new TWEEN.Tween({ moveValue: lastValue }).to({ moveValue: JointValue }, 100) .onStart(function() { originInfo['lastValue'] = JointValue }).onUpdate(function() { switch (type) { case 'position': object[type][axis] = this._object.moveValue break case 'rotation': { const moveAxis = { x: new THREE.Vector3(1, 1, 1), y: new THREE.Vector3(1, 1, 1), z: new THREE.Vector3(1, 1, 1) } matrix.extractBasis(moveAxis.x, moveAxis.y, moveAxis.z) const nM = new THREE.Matrix4() nM.makeRotationAxis(moveAxis[axis], this._object.moveValue) nM.multiply(matrix) object.rotation.setFromRotationMatrix(nM) object.updateWorldMatrix() } break } }).start() editor.solveAttachModel('', false) } else { console.log('模型不存在') } } }) } /** * 接伺服类的数据 * @param ModelInfo * @param tagValue */ this.solveServoSignal = (ModelInfo, tagValue) => { try { const type = ModelInfo.JointType const axis = ModelInfo.Axis const flip = ModelInfo.Flip const Value = ModelInfo.Value const ValueFactor = ModelInfo.ValueFactor // 倍率 const ModelId = ModelInfo.HandlerCode // 模型代码 const object = editor.getObjectById(ModelId) const originInfo = editor.objectIdSet.get(ModelId) if (!originInfo) return const matrix = originInfo['matrix'] const originValue = type === 'rotation' ? originInfo[type]['_' + axis] : originInfo[type][axis] const lastValue = originInfo['lastValue'] === null ? originValue : originInfo['lastValue'] const moveValue = flip * (parseFloat(tagValue) - Value) * ValueFactor if (object) { editor.solveAttachModel('', true) const JointValue = originValue + moveValue new TWEEN.Tween({ moveValue: lastValue }).to({ moveValue: JointValue }, 100) .onStart(function() { originInfo['lastValue'] = JointValue }) .onUpdate(function() { switch (type) { case 'position': object[type][axis] = this._object.moveValue break case 'rotation': { const moveAxis = { x: new THREE.Vector3(1, 1, 1), y: new THREE.Vector3(1, 1, 1), z: new THREE.Vector3(1, 1, 1) } matrix.extractBasis(moveAxis.x, moveAxis.y, moveAxis.z) const nM = new THREE.Matrix4() nM.makeRotationAxis(moveAxis[axis], this._object.moveValue) // nM.makeRotationAxis(moveAxis[axis], JointValue) nM.multiply(matrix) object.rotation.setFromRotationMatrix(nM) object.updateWorldMatrix() } break } }).start() editor.solveAttachModel('', false) } // // if (object) { // editor.solveAttachModel('', true) // object[type][axis] = originValue + (ValueFactor * flip * parseFloat(tagValue) + Value) // editor.solveAttachModel('', false) // } } catch (e) { console.log('solveServoSignal错误') } } /** * 接受机器人类的数据 * @param ModelId * @param JointData * @constructor */ this.JointMoveTo = (ModelId, JointData = {}) => { if (editor.robotList[ModelId]) { const ModelList = editor.robotList[ModelId] // window.updateRobotData(ModelId, JointData) // window.updateLabelInfoJoint(ModelId, JointData) for (let i = 0; i < ModelList.length; i++) { if (ModelList[i].ModelId === '') return this.jointMoveToPromise(JointData, ModelList[i], i, ModelId) } } } this.jointMoveToPromise = (JointData, ModelListData, i, ModelId) => { new Promise(resolve => { const ModelIdJoint = ModelListData.ModelId const object = ModelListData.object const type = ModelListData.type const axis = ModelListData.axis const matrix = ModelListData.matrix const flip = ModelListData.flip const delta = parseFloat(ModelListData.delta) const multiple = ModelListData.multiple const originInfo = editor.objectIdSet.get(ModelIdJoint) if (!originInfo) return const originValue = type === 'rotation' ? originInfo[type]['_' + axis] : originInfo[type][axis] const lastValue = ModelListData.lastValue === null ? originValue : ModelListData.lastValue const moveValue = flip * (parseFloat(JointData['J' + (i + 1)]) - delta) * multiple if (object) { const JointValue = originValue + moveValue new TWEEN.Tween({ moveValue: lastValue }).to({ moveValue: JointValue }, 200) .onStart(function() { editor.robotList[ModelId][i]['lastValue'] = JointValue }) .onUpdate(function() { switch (type) { case 'position': object[type][axis] = this._object.moveValue break case 'rotation': { const moveAxis = { x: new THREE.Vector3(1, 1, 1), y: new THREE.Vector3(1, 1, 1), z: new THREE.Vector3(1, 1, 1) } matrix.extractBasis(moveAxis.x, moveAxis.y, moveAxis.z) const nM = new THREE.Matrix4() nM.makeRotationAxis(moveAxis[axis], this._object.moveValue) // nM.makeRotationAxis(moveAxis[axis], JointValue) nM.multiply(matrix) object.rotation.setFromRotationMatrix(nM) object.updateWorldMatrix() } break } }).start() } }) } this.getAxisValue = (axis, value) => { return JSON.parse('{"' + axis + '":' + value + '}') } this.getAxisValue = (axis, value) => { return JSON.parse('{"' + axis + '":' + value + '}') } this.showWeld = (ModelId, Welding) => { // 徐工专用 if (ModelId === '46DDBCD8-D775-49A4-BB14-30015FF87595') editor.WeldLightVisible1 = !!parseInt(Welding) if (ModelId === '1E96DED2-6EEF-469F-BFE6-8F52FB62C2B0') editor.WeldLightVisible2 = !!parseInt(Welding) } this.showCheckOk = (check) => { // 徐工专用 if (parseInt(check)) { editor.showTagList[3].title = '工件:QY16KC, 检测OK' } else { editor.showTagList[3].title = '工件:QY16KC' } } /** * 显示隐藏物体 * @param m_DeviceName * @param isVisible */ this.visibleObjectToBS = (m_DeviceName, isVisible) => { const currentModel = editor.getObjectById(m_DeviceName) if (currentModel) { currentModel.visible = !!parseInt(isVisible) currentModel.traverse(res => { res.visible = !!parseInt(isVisible) }) currentModel.userData['visible'] = !!parseInt(isVisible) } } /** * 初始化获取TagValue */ this.getOriginTagValue = () => { let msg = '' let socketMsg = '' const keyWord = 'B_C_DT_WebLoaded' msg = 'DT|' + keyWord socketMsg = editor.BSport + msg const topic = editor.BSport.split('?')[2] switch (editor.connectType) { case 1: editor.socket.send(socketMsg) break case 2: editor.mqttClient.publish(topic, msg, 0, error => { if (error) { console.log('Publish error', error) } }) break default: break } } /** * 更新库存状态 * @param dataInfo */ this.drawWareHousePartOne = (dataInfo) => { const scope = this try { const whInfo = JSON.parse(dataInfo) for (const whStoreInfo of whInfo) { const whStoreNum = whStoreInfo.Key // 库位号 唯一值 const whStoreState = whStoreInfo.Value // 立库状态 const whNum = whStoreNum.toString().substring(0, 4) // 立库号 1000一期立库 1003刀具库 1002三坐标测量库 1001机床线旁库 const currentStoreInfo = editor.WareHouse.get(whStoreNum) if (currentStoreInfo) { if (parseInt(whStoreState) === 0) { // 0的时候直接移除库存 editor.removeObject(currentStoreInfo.object) editor.WareHouse.delete(whStoreNum) } else { // 不一样的状态 更新 if (currentStoreInfo.whStoreState !== whStoreState) { // 移除零件,更新库存信息信息 editor.removeObject(currentStoreInfo.object) scope.updateStoreModel(whNum, whStoreNum, whStoreState) currentStoreInfo.whStoreState = whStoreState currentStoreInfo.object = null } } } else { editor.WareHouse.set(whStoreNum, { whNum: whNum, whStoreNum: whStoreNum, whStoreState: whStoreState, object: null }) scope.updateStoreModel(whNum, whStoreNum, whStoreState) } } } catch (e) { console.log('库存解析错误') } } /** * 更新零件 * @param whNum * @param whStoreNum * @param whStoreState */ this.updateStoreModel = (whNum, whStoreNum, whStoreState) => { try { const basicPartModel = editor.WareHouseBasicModel.get('warehousepart' + whStoreState) const basicWareHouseModelData = editor.WareHouseBasicModel.get('warehouse' + whNum) if (basicPartModel && basicWareHouseModelData) { const basicPartModelClone = basicPartModel.clone() const basicPartModelPosition = basicWareHouseModelData[whStoreNum] basicPartModelClone.position.copy(basicPartModelPosition.getWorldPosition(new THREE.Vector3())) editor.scene.add(basicPartModelClone) editor.WareHouse.get(whStoreNum).object = basicPartModelClone } } catch (e) { console.log('库存模型解析错误') } } } export { WebsocketMessageReceive }