10分钟,创建你的第一个点线面低代码应用

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 设置组件属性

这里主要设置组件的名称属性,其他的有程序设置。

端口----》dropdownPort

波特率----dropdownBaud

复选框----HexSendCheckbox

发送区----》send

接收区----recivedData

log----》log

 

2.3 添加 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.4 组件事件与js脚本进行关联

 

3. 结束

更多的细节需要你自己的探索,那就开始你的点线面低代码的探索之旅吧!

有问题可以私信我,也可以在应用程序中找到联系方式,单独交流。

 

 

 

作者:点线面低代码调试助手原文地址:https://www.cnblogs.com/dotlineplane/p/18710914

%s 个评论

要回复文章请先登录注册