mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-26 09:03:54 +08:00
update:改功能易引发坏人滥用,违背开发者初心
This commit is contained in:
+1
-60
@@ -93,7 +93,7 @@ public class DeviceController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/bind/{agentId}")
|
@PostMapping("/bind/{agentId}")
|
||||||
@Operation(summary = "转发POST请求到MQTT网关")
|
@Operation(summary = "设备在线接口")
|
||||||
@RequiresPermissions("sys:role:normal")
|
@RequiresPermissions("sys:role:normal")
|
||||||
public Result<String> forwardToMqttGateway(@PathVariable String agentId, @RequestBody String requestBody) {
|
public Result<String> forwardToMqttGateway(@PathVariable String agentId, @RequestBody String requestBody) {
|
||||||
try {
|
try {
|
||||||
@@ -208,63 +208,4 @@ public class DeviceController {
|
|||||||
deviceService.manualAddDevice(user.getId(), dto);
|
deviceService.manualAddDevice(user.getId(), dto);
|
||||||
return new Result<>();
|
return new Result<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/commands/{deviceId}")
|
|
||||||
@Operation(summary = "发送设备指令")
|
|
||||||
@RequiresPermissions("sys:role:normal")
|
|
||||||
public Result<String> sendDeviceCommand(@PathVariable String deviceId, @RequestBody String command) {
|
|
||||||
try {
|
|
||||||
// 从系统参数中获取MQTT网关地址
|
|
||||||
String mqttGatewayUrl = sysParamsService.getValue("server.mqtt_manager_api", true);
|
|
||||||
if (StringUtils.isBlank(mqttGatewayUrl) || "null".equals(mqttGatewayUrl)) {
|
|
||||||
return new Result<String>().error("MQTT网关地址未配置");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建完整的URL
|
|
||||||
// 获取设备信息以构建mqttClientId
|
|
||||||
DeviceEntity deviceById = deviceService.selectById(deviceId);
|
|
||||||
|
|
||||||
if (!deviceById.getUserId().equals(SecurityUser.getUser().getId())) {
|
|
||||||
return new Result<String>().error("设备不存在");
|
|
||||||
}
|
|
||||||
String macAddress = deviceById != null ? deviceById.getMacAddress() : "unknown";
|
|
||||||
String groupId = deviceById != null ? deviceById.getBoard() : null;
|
|
||||||
if (groupId == null) {
|
|
||||||
groupId = "GID_default";
|
|
||||||
}
|
|
||||||
groupId = groupId.replace(":", "_");
|
|
||||||
macAddress = macAddress.replace(":", "_");
|
|
||||||
|
|
||||||
// 拼接为groupId@@@macAddress@@@deviceId格式
|
|
||||||
String mqttClientId = groupId + "@@@" + macAddress + "@@@" + macAddress;
|
|
||||||
|
|
||||||
String url = "http://" + mqttGatewayUrl + "/api/commands/" + mqttClientId;
|
|
||||||
|
|
||||||
// 设置请求头
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.set("Content-Type", "application/json");
|
|
||||||
|
|
||||||
// 生成Bearer令牌
|
|
||||||
String dateStr = java.time.LocalDate.now()
|
|
||||||
.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
|
||||||
String signatureKey = sysParamsService.getValue("server.mqtt_signature_key", false);
|
|
||||||
if (StringUtils.isBlank(signatureKey)) {
|
|
||||||
return new Result<String>().error("MQTT签名密钥未配置");
|
|
||||||
}
|
|
||||||
String tokenContent = dateStr + signatureKey;
|
|
||||||
String token = org.apache.commons.codec.digest.DigestUtils.sha256Hex(tokenContent);
|
|
||||||
headers.set("Authorization", "Bearer " + token);
|
|
||||||
|
|
||||||
// 构建请求体
|
|
||||||
HttpEntity<String> requestEntity = new HttpEntity<>(command, headers);
|
|
||||||
|
|
||||||
// 发送POST请求
|
|
||||||
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
|
|
||||||
|
|
||||||
// 返回响应
|
|
||||||
return new Result<String>().ok(response.getBody());
|
|
||||||
} catch (Exception e) {
|
|
||||||
return new Result<String>().error("发送指令失败: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -102,21 +102,4 @@ export default {
|
|||||||
});
|
});
|
||||||
}).send();
|
}).send();
|
||||||
},
|
},
|
||||||
// 发送设备指令
|
|
||||||
sendDeviceCommand(deviceId, mcpData, callback) {
|
|
||||||
RequestService.sendRequest()
|
|
||||||
.url(`${getServiceUrl()}/device/commands/${deviceId}`)
|
|
||||||
.method('POST')
|
|
||||||
.data(mcpData)
|
|
||||||
.success((res) => {
|
|
||||||
RequestService.clearRequestTime();
|
|
||||||
callback(res);
|
|
||||||
})
|
|
||||||
.networkFail((err) => {
|
|
||||||
console.error('发送设备指令失败:', err);
|
|
||||||
RequestService.reAjaxFun(() => {
|
|
||||||
this.sendDeviceCommand(deviceId, mcpData, callback);
|
|
||||||
});
|
|
||||||
}).send();
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -64,9 +64,6 @@
|
|||||||
<el-button size="mini" type="text" @click="handleUnbind(scope.row.device_id)">
|
<el-button size="mini" type="text" @click="handleUnbind(scope.row.device_id)">
|
||||||
{{ $t('device.unbind') }}
|
{{ $t('device.unbind') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button v-if="scope.row.deviceStatus === 'online'" size="mini" type="text" @click="handleMcpToolCall(scope.row.device_id)">
|
|
||||||
{{ $t('device.toolCall') }}
|
|
||||||
</el-button>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -82,9 +79,9 @@
|
|||||||
<el-button type="success" size="mini" class="add-device-btn" @click="handleManualAddDevice">
|
<el-button type="success" size="mini" class="add-device-btn" @click="handleManualAddDevice">
|
||||||
{{ $t('device.manualAdd') }}
|
{{ $t('device.manualAdd') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button size="mini" type="danger" icon="el-icon-delete" @click="deleteSelected">{{
|
<el-button size="mini" type="danger" icon="el-icon-delete" @click="deleteSelected">
|
||||||
$t('device.unbind')
|
{{ $t('device.unbind') }}
|
||||||
}}</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="custom-pagination">
|
<div class="custom-pagination">
|
||||||
<el-select v-model="pageSize" @change="handlePageSizeChange" class="page-size-select">
|
<el-select v-model="pageSize" @change="handlePageSizeChange" class="page-size-select">
|
||||||
@@ -92,20 +89,22 @@
|
|||||||
:label="$t('dictManagement.itemsPerPage').replace('{items}', item)" :value="item">
|
:label="$t('dictManagement.itemsPerPage').replace('{items}', item)" :value="item">
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
<button class="pagination-btn" :disabled="currentPage === 1" @click="goFirst">{{
|
<button class="pagination-btn" :disabled="currentPage === 1" @click="goFirst">
|
||||||
$t('dictManagement.firstPage')
|
{{ $t('dictManagement.firstPage') }}
|
||||||
}}</button>
|
</button>
|
||||||
<button class="pagination-btn" :disabled="currentPage === 1" @click="goPrev">{{
|
<button class="pagination-btn" :disabled="currentPage === 1" @click="goPrev">
|
||||||
$t('dictManagement.prevPage')
|
{{ $t('dictManagement.prevPage') }}
|
||||||
}}</button>
|
</button>
|
||||||
<button v-for="page in visiblePages" :key="page" class="pagination-btn"
|
<button v-for="page in visiblePages" :key="page" class="pagination-btn"
|
||||||
:class="{ active: page === currentPage }" @click="goToPage(page)">
|
:class="{ active: page === currentPage }" @click="goToPage(page)">
|
||||||
{{ page }}
|
{{ page }}
|
||||||
</button>
|
</button>
|
||||||
<button class="pagination-btn" :disabled="currentPage === pageCount" @click="goNext">{{
|
<button class="pagination-btn" :disabled="currentPage === pageCount" @click="goNext">
|
||||||
$t('dictManagement.nextPage') }}</button>
|
{{ $t('dictManagement.nextPage') }}
|
||||||
<span class="total-text">{{ $t('dictManagement.totalRecords').replace('{total}', deviceList.length)
|
</button>
|
||||||
}}</span>
|
<span class="total-text">
|
||||||
|
{{ $t('dictManagement.totalRecords').replace('{total}', deviceList.length) }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
@@ -117,7 +116,6 @@
|
|||||||
@refresh="fetchBindDevices(currentAgentId)" />
|
@refresh="fetchBindDevices(currentAgentId)" />
|
||||||
<ManualAddDeviceDialog :visible.sync="manualAddDeviceDialogVisible" :agent-id="currentAgentId"
|
<ManualAddDeviceDialog :visible.sync="manualAddDeviceDialogVisible" :agent-id="currentAgentId"
|
||||||
@refresh="fetchBindDevices(currentAgentId)" />
|
@refresh="fetchBindDevices(currentAgentId)" />
|
||||||
<McpToolCallDialog :visible.sync="mcpToolCallDialogVisible" :device-id="selectedDeviceId" />
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -127,20 +125,17 @@ import Api from '@/apis/api';
|
|||||||
import AddDeviceDialog from "@/components/AddDeviceDialog.vue";
|
import AddDeviceDialog from "@/components/AddDeviceDialog.vue";
|
||||||
import HeaderBar from "@/components/HeaderBar.vue";
|
import HeaderBar from "@/components/HeaderBar.vue";
|
||||||
import ManualAddDeviceDialog from "@/components/ManualAddDeviceDialog.vue";
|
import ManualAddDeviceDialog from "@/components/ManualAddDeviceDialog.vue";
|
||||||
import McpToolCallDialog from "@/components/McpToolCallDialog.vue";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
HeaderBar,
|
HeaderBar,
|
||||||
AddDeviceDialog,
|
AddDeviceDialog,
|
||||||
ManualAddDeviceDialog,
|
ManualAddDeviceDialog
|
||||||
McpToolCallDialog
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
addDeviceDialogVisible: false,
|
addDeviceDialogVisible: false,
|
||||||
manualAddDeviceDialogVisible: false,
|
manualAddDeviceDialogVisible: false,
|
||||||
mcpToolCallDialogVisible: false,
|
|
||||||
selectedDeviceId: '',
|
selectedDeviceId: '',
|
||||||
searchKeyword: "",
|
searchKeyword: "",
|
||||||
activeSearchKeyword: "",
|
activeSearchKeyword: "",
|
||||||
@@ -280,11 +275,6 @@ export default {
|
|||||||
handleManualAddDevice() {
|
handleManualAddDevice() {
|
||||||
this.manualAddDeviceDialogVisible = true;
|
this.manualAddDeviceDialogVisible = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
handleMcpToolCall(deviceId) {
|
|
||||||
this.selectedDeviceId = deviceId;
|
|
||||||
this.mcpToolCallDialogVisible = true;
|
|
||||||
},
|
|
||||||
submitRemark(row) {
|
submitRemark(row) {
|
||||||
if (row._submitting) return;
|
if (row._submitting) return;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user