1. 效果预览
这个例子包括,串口的打开和发送,包括字符串的发送和hex 的发送。最终效果如图。
点线面低代码应用下载
GitHub 下载地址 https://github.com/dotLinePlane-com/dotlineplane/releases
通过百度网盘分享的文件:dotLinePlaneV2.1.0.7z 链接:https://pan.baidu.com/s/1XUl32fFD3ssZoPMqC4NmQw?pwd=qn0d 提取码:qn0d
2. 具体步骤
创建一个应用主要有四个步骤,包括:拖拽组件、设置组件属性、编写js脚本和设置组件事件与脚本关联。
2.1 拖拽组件
界面的右边选择拖拽到画布中。
使用的组件有 dropdown (端口和波特率)、按钮(打开和发送)、复选框(Hex 发送)、文本输入框(发送区)和 多行文本输入框(接收区和log)
2.2 添加 js 脚本
***添加 init 脚本时,注意需要在Settings 中打开 在应用程序加载时运行此查询
init 脚本- //init 脚本
- // 获取串口列表
- const ports = await serialAPI.getSerialPorts();
- console.log("v port :", ports);
- // 格式化串口数据
- let formattedPorts = ports.map(port => ({
- disable: false,
- visible: true,
- value: port.path,
- label: port.friendlyName || port.path,
- }));
- console.log("port:", formattedPorts);
- // 获取 defaultPortsValue, portsLabel 和 portsValue
- const defaultPortsValue = formattedPorts.length > 0 ? formattedPorts[0].value : null;
- const portsLabel = formattedPorts.map(port => port.label);
- const portsValue = formattedPorts.map(port => port.value);
- const portsSelect = {
- defaultPortsValue,
- portsLabel,
- portsValue,
- };
- const baudsValue = [9600, 115200];
- const baudsLabel = ["9600", "115200"];
- const defaultBaudsValue = baudsValue[0];
- const baudsSelect = {
- defaultBaudsValue,
- baudsValue,
- baudsLabel,
- };
- // 更新 formattedPorts 对象结构
- const formattedPortsObject = {
- portsSelect,
- baudsSelect,
- };
- console.log("formattedPortsObject:", formattedPortsObject);
- // 设置页面变量
- await actions.setPageVariable('ports', formattedPortsObject);
- await actions.setPageVariable('serialRx', '');
- await actions.setPageVariable('isOpen', false);
- // 定义处理串口数据的函数
- const handleSerialData = async (path, data) => {
- if (path === page.variables.usedPort) {
- const receiveTime = Date.now();
- console.log(`[${new Date(receiveTime).toISOString()}] Received data:`, data);
- await actions.setPageVariable('serialRx', data);
- }
- };
- // 初始化串口连接
- const initializeSerialConnection = async () => {
- if (page.variables.isOpen) {
- // 设置使用的串口
- await actions.setPageVariable('usedPort', components.dropdownPort.value);
- serialAPI.onSerialData(components.dropdownPort.value, handleSerialData);
- } else {
- await actions.setPageVariable('usedPort', '');
- // serialAPI.offSerialData(portRef.current, handleSerialData);
- }
- };
- // 在页面加载时执行初始化
- await initializeSerialConnection();
- // 返回格式化后的串口对象
- return formattedPortsObject;
复制代码
openPort 脚本- //openPort
- function mergeUint8Arrays(arrays) {
- console.log(`Received data:`, arrays);
- if (arrays instanceof Uint8Array) {
- arrays = [arrays];
- }
- if (!Array.isArray(arrays)) {
- console.error("Input is not an array.");
- return null;
- }
- // 确保数组中的每个元素都是 Uint8Array
- for (let i = 0; i < arrays.length; i++) {
- if (!(arrays[i] instanceof Uint8Array)) {
- console.error(`Element at index ${i} is not a Uint8Array.`);
- return null;
- }
- }
- // 计算总长度
- const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
- // 创建新的 Uint8Array
- const mergedArray = new Uint8Array(totalLength);
- // 复制数据
- let offset = 0;
- arrays.forEach(arr => {
- mergedArray.set(arr, offset);
- offset += arr.length;
- });
- return mergedArray;
- }
- const handleSerialData = async (path, data) => {
- if (path === page.variables.usedPort) {
- const receiveTime = Date.now();
- console.log(`[${new Date(receiveTime).toISOString()}] Received data:`, data);
- const mergeData = mergeUint8Arrays(data);
- const decoder = new TextDecoder('utf-8');
- const stringData = decoder.decode(mergeData);
- console.log("serialRx:",stringData);
- await actions.setPageVariable('serialRx', stringData);
- }
- };
- if (!page.variables.isOpen) {
- // Open the serial port
- const config = {
- path:components.dropdownPort.value,
- baudRate: parseInt(components.dropdownBaud.value, 10),
- dataBits:8,
- parity:'none',
- stopBits:1,
- // dataBits: parseInt(components.dropdownBits.value, 10),
- // parity: components.dropdownCrc.value === 'NONE' ? 'none' : components.dropdownCrc.value.toLowerCase(),
- // stopBits: parseInt(components.dropdownStop.value, 10),
- };
- try {
- const result = await serialAPI.openSerialPort(config);
- console.log(result);
- await actions.setPageVariable('usedPort', components.dropdownPort.value);
- serialAPI.onSerialData(components.dropdownPort.value, handleSerialData);
- await actions.setPageVariable('isOpen', true);
- components.openButton.setText("关闭");
- } catch (error) {
- console.error('Failed to open serial port:', error);
- }
- } else {
- // Close the serial port
- try {
- await serialAPI.closeSerialPort(page.variables.usedPort);
- serialAPI.offSerialData(page.variables.usedPort, handleSerialData);
- await actions.setPageVariable('isOpen', false);
- components.openButton.setText("打开");
- } catch (error) {
- console.error('Failed to close serial port:', error);
- await actions.setPageVariable('isOpen', false);
- components.openButton.setText("打开");
- if(page.variables.usedPort){
- serialAPI.offSerialData(page.variables.usedPort, handleSerialData);
- }
- }
- }
- return 0;
复制代码
sendData 脚本- //sendData
- function hexStringToUint8Array(hexString) {
- // 确保字符串长度为偶数
- if (hexString.length % 2 !== 0) {
- return null;
- }
- // 创建一个 Uint8Array,长度为字符串长度的一半
- const length = hexString.length / 2;
- const uint8Array = new Uint8Array(length);
- // 遍历字符串,每两个字符解析为一个字节
- for (let i = 0; i < length; i++) {
- const byteHex = hexString.substr(i * 2, 2); // 提取两个字符
- uint8Array[i] = parseInt(byteHex, 16); // 将 16 进制字符串解析为数字
- }
- return uint8Array;
- }
- if(page.variables.isOpen){
- if(!components.HexSendCheckbox.value){
- serialAPI.writeSerialPort(page.variables.usedPort,components.sendData.value);
- }else{
- const hexSend = hexStringToUint8Array(components.sendData.value);
- if(hexSend){
- serialAPI.writeSerialPort(page.variables.usedPort,hexSend);
- // actions.showAlert("info:"+ "发送成功"); // 使用 ToolJet 的 toast 组件
- actions.setVariable("infoMessage", "发送成功");
- // queries.log.run()
- await actions.runQuery('log',{message: "发送成功"});
- }
- }
- }
复制代码
log 脚本- //log
- // 更新 log 内容
- components.log.setText(components.log.value + variables.infoMessage + "\r\n");
- // 获取 TextArea 元素
- // 获取外层 div 元素
- const textareaWrapper = document.getElementById(components.log.id);
- // 从外层 div 中找到 textarea 元素
- const textareaElement = textareaWrapper ? textareaWrapper.querySelector("textarea") : null;
- // 检查是否成功获取 textarea
- if (textareaElement) {
- // 滚动到 textarea 的底部
- textareaElement.scrollTop = textareaElement.scrollHeight;
- }
复制代码
2.3 设置组件属性
这里主要设置组件的名称属性,其他的有程序设置。
端口组件:
名称:dropdownPort
默认值:queries.init.data.portsSelect.defaultPortsValue
选项值:queries.init.data.portsSelect.portsValue
选项标签:queries.init.data.portsSelect.portsLabel
波特率组件:
名称:dropdownBaud
默认值:queries.init.data.baudsSelect.defaultBaudsValue
选项值:queries.init.data.baudsSelect.baudsValue
选项标签:queries.init.data.baudsSelect.baudsLabel
打开按钮组件
名称:openButton
Hex 发送组件
名称:HexSendCheckbox
发送区组件
名称:sendData
接收区组件
名称:recivedData
默认值:page.variables.serialRx *注意:需要使用{{}},符号包裹起来
log 组件
名称:log
2.4 组件事件与js脚本进行关联
打开和发送组件,都需要添加关联事件
3. 结束
更多的细节需要你自己的探索,那就开始你的点线面低代码的探索之旅吧!
有问题可以私信我,也可以在应用程序中找到联系方式,单独交流。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |