Как создать простой LoRa мессенджер: обмен текстовыми сообщениями между устройствами без интернета26.02.2024 11:15
[
{
"id": "2f52923ccb63864b",
"type": "tab",
"label": "LoRa P2P Messaging",
"disabled": false,
"info": "",
"env": []
},
{
"id": "bb3960f039b0d5d9",
"type": "group",
"z": "2f52923ccb63864b",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"9362510d02f2a3cd",
"653c14cbd7d04855",
"411dc5558acb5d69",
"7c928c5461e79357",
"3d751b388616d680",
"d7f18a1a41328fc2",
"39310643b351cbe9",
"0ad15eca9748f8c2",
"2aa5a90b9a47e61a",
"41c7e933bc23bf15",
"e226f98ef20c6e3c",
"f193efb9e856e239",
"8215f7a39798258c",
"9f6693be1c896628",
"796a0c4c7349efdc",
"d2b59a73f776232a",
"c9a150394bb8dd8b",
"229f643b2e4dc980"
],
"x": 34,
"y": 79,
"w": 1892,
"h": 342
},
{
"id": "0c3ab2711ef23cd5",
"type": "group",
"z": "2f52923ccb63864b",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"3fcbc4e3b39e37e0",
"550ac146763bb1cf",
"ded89b84d1895114",
"29ee0d0fd91ab5d4",
"e03995b19d8f6ff1",
"3a8125696d200c02",
"31d9cb982c9d1c95",
"30d506a8ea905666",
"9f9472d611ecf562"
],
"x": 34,
"y": 479,
"w": 1032,
"h": 202
},
{
"id": "9362510d02f2a3cd",
"type": "debug",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "3: Кодированные данные",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 940,
"y": 180,
"wires": []
},
{
"id": "653c14cbd7d04855",
"type": "debug",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "1: Сырые данные",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 390,
"y": 120,
"wires": []
},
{
"id": "3fcbc4e3b39e37e0",
"type": "function",
"z": "2f52923ccb63864b",
"g": "0c3ab2711ef23cd5",
"name": "Декодирование данных",
"func": "// Установите значения для соответствия символов и их кодировок\nconst encodingTable = {\n ' ': '00',\n '.': '01',\n ',': '02',\n '!': '03',\n '?': '04',\n '-': '05',\n '(': '06',\n ')': '07',\n 'а': '08',\n 'б': '09',\n 'в': '0A',\n 'г': '0B',\n 'д': '0C',\n 'е': '0D',\n 'ж': '0E',\n 'з': '0F',\n 'и': '10',\n 'й': '11',\n 'к': '12',\n 'л': '13',\n 'м': '14',\n 'н': '15',\n 'о': '16',\n 'п': '17',\n 'р': '18',\n 'с': '19',\n 'т': '1A',\n 'у': '1B',\n 'ф': '1C',\n 'х': '1D',\n 'ц': '1E',\n 'ч': '1F',\n 'ш': '20',\n 'щ': '21',\n 'ъ': '22',\n 'ы': '23',\n 'ь': '24',\n 'э': '25',\n 'ю': '26',\n 'я': '27',\n 'А': '28',\n 'Б': '29',\n 'В': '2A',\n 'Г': '2B',\n 'Д': '2C',\n 'Е': '2D',\n 'Ё': '2E',\n 'Ж': '2F',\n 'З': '30',\n 'И': '31',\n 'Й': '32',\n 'К': '33',\n 'Л': '34',\n 'М': '35',\n 'Н': '36',\n 'О': '37',\n 'П': '38',\n 'Р': '39',\n 'С': '3A',\n 'Т': '3B',\n 'У': '3C',\n 'Ф': '3D',\n 'Х': '3E',\n 'Ц': '3F',\n 'Ч': '40',\n 'Ш': '41',\n 'Щ': '42',\n 'Ъ': '43',\n 'Ы': '44',\n 'Ь': '45',\n 'Э': '46',\n 'Ю': '47',\n 'Я': '48',\n ', а': '49',\n ', б': '4A',\n ', в': '4B',\n ', г': '4C',\n ', д': '4D',\n ', е': '4E',\n ', ж': '4F',\n ', з': '50',\n ', и': '51',\n ', й': '52',\n ', к': '53',\n ', л': '54',\n ', м': '55',\n ', н': '56',\n ', о': '57',\n ', п': '58',\n ', р': '59',\n ', с': '5A',\n ', т': '5B',\n ', у': '5C',\n ', ф': '5D',\n ', х': '5E',\n ', ц': '5F',\n ', ч': '60',\n ', ш': '61',\n ', щ': '62',\n ', ъ': '63',\n ', ы': '64',\n ', ь': '65',\n ', э': '66',\n ', ю': '67',\n ', я': '68',\n ' а ': '69',\n ' в ': '6A',\n ' и ': '6B',\n ' к ': '6C',\n ' с ': '6D',\n ' у ': '6E',\n ' я ': '6F',\n 'будет': '70',\n 'буду': '71',\n 'бы': '72',\n 'был': '73',\n 'была': '74',\n 'были': '75',\n 'вас': '76',\n 'вот': '77',\n 'все': '78',\n 'всех': '79',\n 'вы': '7A',\n 'где': '7B',\n 'для': '7C',\n 'его': '7D',\n 'ее': '7E',\n 'ей': '7F',\n 'ем': '80',\n 'ему': '81',\n 'если': '82',\n 'есть': '83',\n 'ею': '84',\n 'зачем': '85',\n 'здесь': '86',\n 'из': '87',\n 'или': '88',\n 'их': '89',\n 'как': '8A',\n 'какая': '8B',\n 'какие': '8C',\n 'какое': '8D',\n 'какой': '8E',\n 'когда': '8F',\n 'которая': '90',\n 'которое': '91',\n 'которые': '92',\n 'который': '93',\n 'кто': '94',\n 'меня': '95',\n 'мне': '96',\n 'мог': '97',\n 'могла': '98',\n 'могли': '99',\n 'могу': '9A',\n 'могут': '9B',\n 'мое': '9C',\n 'моего': '9D',\n 'моей': '9E',\n 'может': '9F',\n 'можете': 'A0',\n 'мои': 'A1',\n 'моим': 'A2',\n 'моих': 'A3',\n 'мой': 'A4',\n 'моя': 'A5',\n 'мы': 'A6',\n 'на': 'A7',\n 'наш': 'A8',\n 'наша': 'A9',\n 'наше': 'AA',\n 'наши': 'AB',\n 'не': 'AC',\n 'него': 'AD',\n 'нему': 'AE',\n 'ним': 'AF',\n 'но': 'B0',\n 'он': 'B1',\n 'они': 'B2',\n 'от': 'B3',\n 'отсюда': 'B4',\n 'оттуда': 'B5',\n 'по': 'B6',\n 'потом': 'B7',\n 'почему': 'B8',\n 'свое': 'B9',\n 'свои': 'BA',\n 'свой': 'BB',\n 'своя': 'BC',\n 'сейчас': 'BD',\n 'сказал': 'BE',\n 'сказала': 'BF',\n 'сколько': 'C0',\n 'сюда': 'C1',\n 'такая': 'C2',\n 'также': 'C3',\n 'такие': 'C4',\n 'такое': 'C5',\n 'такой': 'C6',\n 'там': 'C7',\n 'твое': 'C8',\n 'твоего': 'C9',\n 'твоей': 'CA',\n 'твоем': 'CB',\n 'твои': 'CC',\n 'твоих': 'CD',\n 'твой': 'CE',\n 'твоя': 'CF',\n 'тебя': 'D0',\n 'теперь': 'D1',\n 'то': 'D2',\n 'тогда': 'D3',\n 'туда': 'D4',\n 'тут': 'D5',\n 'ты': 'D6',\n 'что': 'D7',\n 'этим': 'D8',\n 'это': 'D9',\n 'этого': 'DA',\n 'этой': 'DB',\n 'этому': 'DC',\n 'этот': 'DD',\n 'хм': 'DE',\n '1': 'DF',\n '2': 'E0',\n '3': 'E1',\n '4': 'E2',\n '5': 'E3',\n '6': 'E4',\n '7': 'E5',\n '8': 'E6',\n '9': 'E7',\n '0': 'E8',\n 'Привет': 'E9',\n 'Привет,': 'EA',\n 'Хабр': 'EB'\n};\n\n// Обратное преобразование\nfunction decodeString(encodedString) {\n let decodedString = '';\n\n for (let i = 0; i < encodedString.length; i += 2) {\n const code = encodedString.substr(i, 2);\n\n // Поиск символа в таблице\n const char = Object.keys(encodingTable).find(key => encodingTable[key] === code);\n\n // Если символ найден, добавляем его к раскодированной строке\n if (char) {\n decodedString += char;\n } else {\n // Если символ не найден, оставляем его без изменений\n decodedString += code;\n }\n }\n\n // Создаем объект сообщения и возвращаем результат\n const msg = { payload: decodedString };\n return msg;\n}\n\n// Закодированная строка для обратного преобразования\nconst encodedString = msg.payload;\n\n// Применяем функцию к закодированной строке\nconst resultDecoding = decodeString(encodedString);\n\n// Выводим результат в debug\nreturn resultDecoding;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 590,
"y": 580,
"wires": [
[
"550ac146763bb1cf",
"ded89b84d1895114",
"31d9cb982c9d1c95"
]
]
},
{
"id": "550ac146763bb1cf",
"type": "debug",
"z": "2f52923ccb63864b",
"g": "0c3ab2711ef23cd5",
"name": "6: Декодированные данные",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 880,
"y": 520,
"wires": []
},
{
"id": "411dc5558acb5d69",
"type": "function",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "Кодирование данных",
"func": "// Протокол обмена\nconst encodingTable = {\n ' ': '00',\n '.': '01',\n ',': '02',\n '!': '03',\n '?': '04',\n '-': '05',\n '(': '06',\n ')': '07',\n 'а': '08',\n 'б': '09',\n 'в': '0A',\n 'г': '0B',\n 'д': '0C',\n 'е': '0D',\n 'ж': '0E',\n 'з': '0F',\n 'и': '10',\n 'й': '11',\n 'к': '12',\n 'л': '13',\n 'м': '14',\n 'н': '15',\n 'о': '16',\n 'п': '17',\n 'р': '18',\n 'с': '19',\n 'т': '1A',\n 'у': '1B',\n 'ф': '1C',\n 'х': '1D',\n 'ц': '1E',\n 'ч': '1F',\n 'ш': '20',\n 'щ': '21',\n 'ъ': '22',\n 'ы': '23',\n 'ь': '24',\n 'э': '25',\n 'ю': '26',\n 'я': '27',\n 'А': '28',\n 'Б': '29',\n 'В': '2A',\n 'Г': '2B',\n 'Д': '2C',\n 'Е': '2D',\n 'Ё': '2E',\n 'Ж': '2F',\n 'З': '30',\n 'И': '31',\n 'Й': '32',\n 'К': '33',\n 'Л': '34',\n 'М': '35',\n 'Н': '36',\n 'О': '37',\n 'П': '38',\n 'Р': '39',\n 'С': '3A',\n 'Т': '3B',\n 'У': '3C',\n 'Ф': '3D',\n 'Х': '3E',\n 'Ц': '3F',\n 'Ч': '40',\n 'Ш': '41',\n 'Щ': '42',\n 'Ъ': '43',\n 'Ы': '44',\n 'Ь': '45',\n 'Э': '46',\n 'Ю': '47',\n 'Я': '48',\n ', а': '49',\n ', б': '4A',\n ', в': '4B',\n ', г': '4C',\n ', д': '4D',\n ', е': '4E',\n ', ж': '4F',\n ', з': '50',\n ', и': '51',\n ', й': '52',\n ', к': '53',\n ', л': '54',\n ', м': '55',\n ', н': '56',\n ', о': '57',\n ', п': '58',\n ', р': '59',\n ', с': '5A',\n ', т': '5B',\n ', у': '5C',\n ', ф': '5D',\n ', х': '5E',\n ', ц': '5F',\n ', ч': '60',\n ', ш': '61',\n ', щ': '62',\n ', ъ': '63',\n ', ы': '64',\n ', ь': '65',\n ', э': '66',\n ', ю': '67',\n ', я': '68',\n ' а ': '69',\n ' в ': '6A',\n ' и ': '6B',\n ' к ': '6C',\n ' с ': '6D',\n ' у ': '6E',\n ' я ': '6F',\n 'будет': '70',\n 'буду': '71',\n 'бы': '72',\n 'был': '73',\n 'была': '74',\n 'были': '75',\n 'вас': '76',\n 'вот': '77',\n 'все': '78',\n 'всех': '79',\n 'вы': '7A',\n 'где': '7B',\n 'для': '7C',\n 'его': '7D',\n 'ее': '7E',\n 'ей': '7F',\n 'ем': '80',\n 'ему': '81',\n 'если': '82',\n 'есть': '83',\n 'ею': '84',\n 'зачем': '85',\n 'здесь': '86',\n 'из': '87',\n 'или': '88',\n 'их': '89',\n 'как': '8A',\n 'какая': '8B',\n 'какие': '8C',\n 'какое': '8D',\n 'какой': '8E',\n 'когда': '8F',\n 'которая': '90',\n 'которое': '91',\n 'которые': '92',\n 'который': '93',\n 'кто': '94',\n 'меня': '95',\n 'мне': '96',\n 'мог': '97',\n 'могла': '98',\n 'могли': '99',\n 'могу': '9A',\n 'могут': '9B',\n 'мое': '9C',\n 'моего': '9D',\n 'моей': '9E',\n 'может': '9F',\n 'можете': 'A0',\n 'мои': 'A1',\n 'моим': 'A2',\n 'моих': 'A3',\n 'мой': 'A4',\n 'моя': 'A5',\n 'мы': 'A6',\n 'на': 'A7',\n 'наш': 'A8',\n 'наша': 'A9',\n 'наше': 'AA',\n 'наши': 'AB',\n 'не': 'AC',\n 'него': 'AD',\n 'нему': 'AE',\n 'ним': 'AF',\n 'но': 'B0',\n 'он': 'B1',\n 'они': 'B2',\n 'от': 'B3',\n 'отсюда': 'B4',\n 'оттуда': 'B5',\n 'по': 'B6',\n 'потом': 'B7',\n 'почему': 'B8',\n 'свое': 'B9',\n 'свои': 'BA',\n 'свой': 'BB',\n 'своя': 'BC',\n 'сейчас': 'BD',\n 'сказал': 'BE',\n 'сказала': 'BF',\n 'сколько': 'C0',\n 'сюда': 'C1',\n 'такая': 'C2',\n 'также': 'C3',\n 'такие': 'C4',\n 'такое': 'C5',\n 'такой': 'C6',\n 'там': 'C7',\n 'твое': 'C8',\n 'твоего': 'C9',\n 'твоей': 'CA',\n 'твоем': 'CB',\n 'твои': 'CC',\n 'твоих': 'CD',\n 'твой': 'CE',\n 'твоя': 'CF',\n 'тебя': 'D0',\n 'теперь': 'D1',\n 'то': 'D2',\n 'тогда': 'D3',\n 'туда': 'D4',\n 'тут': 'D5',\n 'ты': 'D6',\n 'что': 'D7',\n 'этим': 'D8',\n 'это': 'D9',\n 'этого': 'DA',\n 'этой': 'DB',\n 'этому': 'DC',\n 'этот': 'DD',\n 'хм': 'DE',\n '1': 'DF',\n '2': 'E0',\n '3': 'E1',\n '4': 'E2',\n '5': 'E3',\n '6': 'E4',\n '7': 'E5',\n '8': 'E6',\n '9': 'E7',\n '0': 'E8',\n 'Привет': 'E9',\n 'Привет,': 'EA',\n 'Хабр': 'EB'\n};\n\n// Функция преобразования строки в кодировку\nfunction encodeString(inputString) {\n const maxBytes = 51;\n let encodedStrings = [];\n\n // Если строка больше 51 байта, разбиваем на посылки\n if (Buffer.from(inputString, 'utf-8').length > maxBytes) {\n let currentChunk = '';\n let currentChunkBytes = 0;\n\n for (let i = 0; i < inputString.length; i++) {\n const char = inputString[i];\n const charBytes = Buffer.from(char, 'utf-8').length;\n\n // Проверяем, можно ли добавить символ к текущей посылке\n if (currentChunkBytes + charBytes <= maxBytes) {\n currentChunk += char;\n currentChunkBytes += charBytes;\n } else {\n // Если символ не помещается, добавляем текущую посылку в результат\n encodedStrings.push(encodeChunk(currentChunk));\n\n // Начинаем новую посылку\n currentChunk = char;\n currentChunkBytes = charBytes;\n }\n }\n\n // Добавляем последнюю посылку в результат\n if (currentChunk !== '') {\n encodedStrings.push(encodeChunk(currentChunk));\n }\n } else {\n // Строка помещается в одну посылку\n encodedStrings.push(encodeChunk(inputString));\n }\n\n // Возвращаем генератор, чтобы поочередно возвращать строки с задержкой\n let index = 0;\n const sendNext = () => {\n if (index < encodedStrings.length) {\n const value = encodedStrings[index++];\n setTimeout(() => {\n node.send({ payload: value });\n sendNext();\n }, 2000); // Задержка в 2 секунд\n }\n };\n\n sendNext();\n}\n\n// Вспомогательная функция для кодирования части строки\nfunction encodeChunk(chunk) {\n let encodedChunk = '';\n\n // Разбиваем часть строки на слова\n const words = chunk.split(' ');\n\n // Кодируем каждое слово отдельно\n for (let i = 0; i < words.length; i++) {\n const word = words[i];\n\n // Проверяем, является ли слово словом в словаре\n if (encodingTable.hasOwnProperty(word)) {\n encodedChunk += encodingTable[word];\n } else {\n // Кодируем каждый символ слова отдельно\n for (let j = 0; j < word.length; j++) {\n const char = word[j];\n\n // Проверяем, есть ли символ в таблице\n if (encodingTable.hasOwnProperty(char)) {\n encodedChunk += encodingTable[char];\n } else {\n // Если символ отсутствует в таблице, оставляем его без изменений\n encodedChunk += char;\n }\n }\n }\n\n // Добавляем пробел между словами\n if (i < words.length - 1) {\n encodedChunk += encodingTable[' '];\n }\n }\n\n return encodedChunk;\n}\n\n// Применяем функцию к входной строке\nconst inputString = msg.payload;\nencodeString(inputString);",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 680,
"y": 240,
"wires": [
[
"3d751b388616d680",
"d7f18a1a41328fc2",
"9362510d02f2a3cd"
]
]
},
{
"id": "7c928c5461e79357",
"type": "ui_text_input",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "",
"label": "Данные для отправки",
"tooltip": "",
"group": "afb27fbd0a803a11",
"order": 1,
"width": 0,
"height": 0,
"passthru": true,
"mode": "text",
"delay": "1000",
"topic": "topic",
"sendOnBlur": true,
"className": "",
"topicType": "msg",
"x": 160,
"y": 240,
"wires": [
[
"653c14cbd7d04855",
"e226f98ef20c6e3c",
"8215f7a39798258c"
]
]
},
{
"id": "ded89b84d1895114",
"type": "ui_text",
"z": "2f52923ccb63864b",
"g": "0c3ab2711ef23cd5",
"group": "afb27fbd0a803a11",
"order": 3,
"width": 0,
"height": 0,
"name": "",
"label": "Получено сообщение:",
"format": "{{msg.payload}}",
"layout": "row-left",
"className": "",
"style": false,
"font": "",
"fontSize": "",
"color": "#000000",
"x": 870,
"y": 580,
"wires": []
},
{
"id": "3d751b388616d680",
"type": "ui_text",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"group": "afb27fbd0a803a11",
"order": 2,
"width": 0,
"height": 0,
"name": "",
"label": "Кодированное сообщение:",
"format": "{{msg.payload}}",
"layout": "row-left",
"className": "",
"style": false,
"font": "",
"fontSize": "",
"color": "#000000",
"x": 940,
"y": 300,
"wires": []
},
{
"id": "d7f18a1a41328fc2",
"type": "function",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "Формирование AT команды",
"func": "// Получаем входные данные из сообщения msg.payload\nvar inputString = msg.payload;\n\n// Формируем строку в требуемом формате\nvar outputString = 'AT+PSEND=' + inputString;\n\n// Создаем новый объект сообщения и устанавливаем в него преобразованную строку\nmsg.payload = outputString;\n\n// Возвращаем объект сообщения\nreturn msg;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 940,
"y": 240,
"wires": [
[
"39310643b351cbe9",
"0ad15eca9748f8c2",
"9f6693be1c896628"
]
]
},
{
"id": "39310643b351cbe9",
"type": "serial out",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "",
"serial": "baa0d15198c00a18",
"x": 1820,
"y": 240,
"wires": []
},
{
"id": "29ee0d0fd91ab5d4",
"type": "serial in",
"z": "2f52923ccb63864b",
"g": "0c3ab2711ef23cd5",
"name": "",
"serial": "baa0d15198c00a18",
"x": 130,
"y": 580,
"wires": [
[
"e03995b19d8f6ff1"
]
]
},
{
"id": "0ad15eca9748f8c2",
"type": "debug",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "4: Отправка данных на UART",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1250,
"y": 180,
"wires": []
},
{
"id": "e03995b19d8f6ff1",
"type": "function",
"z": "2f52923ccb63864b",
"g": "0c3ab2711ef23cd5",
"name": "Фильтруем Payload",
"func": "// Получаем входные данные из сообщения msg.payload\nvar inputString = msg.payload;\n\n// Разбиваем строку по символу \":\" и выбираем последний элемент массива\nvar parts = inputString.split(':');\nvar extractedValue = parts[parts.length - 1];\n\n// Создаем новый объект сообщения и устанавливаем в него извлеченное значение\nmsg.payload = extractedValue;\n\n// Возвращаем объект сообщения\nreturn msg;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 340,
"y": 580,
"wires": [
[
"3fcbc4e3b39e37e0"
]
]
},
{
"id": "2aa5a90b9a47e61a",
"type": "ui_button",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "",
"group": "afb27fbd0a803a11",
"order": 4,
"width": 0,
"height": 0,
"passthru": false,
"label": "Режим P2P",
"tooltip": "",
"color": "",
"bgcolor": "",
"className": "",
"icon": "",
"payload": "AT+NWM=0",
"payloadType": "str",
"topic": "topic",
"topicType": "msg",
"x": 1590,
"y": 380,
"wires": [
[
"39310643b351cbe9"
]
]
},
{
"id": "41c7e933bc23bf15",
"type": "ui_button",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "",
"group": "afb27fbd0a803a11",
"order": 7,
"width": 0,
"height": 0,
"passthru": false,
"label": "Режим LoRaWAN",
"tooltip": "",
"color": "",
"bgcolor": "",
"className": "",
"icon": "",
"payload": "AT+NWM=1",
"payloadType": "str",
"topic": "topic",
"topicType": "msg",
"x": 1570,
"y": 340,
"wires": [
[
"39310643b351cbe9"
]
]
},
{
"id": "e226f98ef20c6e3c",
"type": "ui_button",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "",
"group": "afb27fbd0a803a11",
"order": 5,
"width": 0,
"height": 0,
"passthru": true,
"label": "Передача сообщений ВКЛ",
"tooltip": "",
"color": "",
"bgcolor": "",
"className": "",
"icon": "",
"payload": "AT+PRECV=0",
"payloadType": "str",
"topic": "topic",
"topicType": "msg",
"x": 420,
"y": 180,
"wires": [
[
"d2b59a73f776232a",
"229f643b2e4dc980"
]
]
},
{
"id": "f193efb9e856e239",
"type": "ui_button",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "",
"group": "afb27fbd0a803a11",
"order": 6,
"width": 0,
"height": 0,
"passthru": true,
"label": "Прием сообщений ВКЛ",
"tooltip": "",
"color": "",
"bgcolor": "",
"className": "",
"icon": "",
"payload": "AT+PRECV=65534",
"payloadType": "str",
"topic": "topic",
"topicType": "msg",
"x": 1550,
"y": 300,
"wires": [
[
"39310643b351cbe9"
]
]
},
{
"id": "8215f7a39798258c",
"type": "delay",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "",
"pauseType": "delay",
"timeout": "250",
"timeoutUnits": "milliseconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 390,
"y": 240,
"wires": [
[
"411dc5558acb5d69"
]
]
},
{
"id": "9f6693be1c896628",
"type": "function",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "Задержка на Прием ВКЛ",
"func": "// Получаем контекст текущего узла\nvar context = flow.get('sessionContext') || {};\n\n// Инициализируем массив для хранения сообщений текущей сессии\ncontext.sessionMessages = context.sessionMessages || [];\n\n// Добавляем новые сообщения в массив\ncontext.sessionMessages = context.sessionMessages.concat(msg.payload);\n\n// Устанавливаем таймер на 4 секунд для завершения сессии\nif (context.sessionTimer) {\n clearTimeout(context.sessionTimer);\n}\n\ncontext.sessionTimer = setTimeout(function () {\n // Когда таймер срабатывает, находим последнее сообщение\n var lastMessage = context.sessionMessages[context.sessionMessages.length - 1];\n\n // Очищаем контекст для следующей сессии\n context.sessionMessages = [];\n context.sessionTimer = null;\n\n // Возвращаем последнее сообщение\n node.send({ payload: lastMessage });\n}, 2500); // 2 секунд таймер\n\n// Если есть еще время до конца сессии, сохраняем контекст\nflow.set('sessionContext', context);\n\n// Возвращаем null или что-то еще, чтобы показать, что обработка не завершена\nreturn null;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1240,
"y": 300,
"wires": [
[
"f193efb9e856e239",
"796a0c4c7349efdc"
]
]
},
{
"id": "3a8125696d200c02",
"type": "ui_template",
"z": "2f52923ccb63864b",
"g": "0c3ab2711ef23cd5",
"group": "afb27fbd0a803a11",
"name": "History",
"order": 9,
"width": "10",
"height": "5",
"format": "",
"storeOutMessages": true,
"fwdInMessages": true,
"resendOnRefresh": true,
"templateScope": "local",
"className": "",
"x": 980,
"y": 640,
"wires": [
[]
]
},
{
"id": "31d9cb982c9d1c95",
"type": "function",
"z": "2f52923ccb63864b",
"g": "0c3ab2711ef23cd5",
"name": "History",
"func": "// Проверяем, если кнопка \"clearHistory\" была нажата\nif (msg.payload === ' ') {\n // Очищаем историю\n context.history = [];\n}\n\n// Добавление нового сообщения в историю\ncontext.history = context.history || [];\ncontext.history.push(msg.payload);\n\n// Ограничение длины истории (если нужно)\nvar maxLength = 25; // Максимальная длина истории\nif (context.history.length > maxLength) {\n context.history.shift(); // Удаляем самое старое сообщение\n}\n\n// Отправка истории на вход ui_template\nreturn { payload: context.history.join('
') };",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 820,
"y": 640,
"wires": [
[
"3a8125696d200c02"
]
]
},
{
"id": "30d506a8ea905666",
"type": "ui_button",
"z": "2f52923ccb63864b",
"g": "0c3ab2711ef23cd5",
"name": "",
"group": "afb27fbd0a803a11",
"order": 8,
"width": 0,
"height": 0,
"passthru": false,
"label": "СlearHistory",
"tooltip": "",
"color": "",
"bgcolor": "",
"className": "",
"icon": "",
"payload": " ",
"payloadType": "str",
"topic": "topic",
"topicType": "msg",
"x": 630,
"y": 640,
"wires": [
[
"31d9cb982c9d1c95"
]
]
},
{
"id": "796a0c4c7349efdc",
"type": "debug",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "5: Переключене Прием ВКЛ",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1570,
"y": 180,
"wires": []
},
{
"id": "d2b59a73f776232a",
"type": "debug",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "2: Переключене Передача ВКЛ",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 720,
"y": 120,
"wires": []
},
{
"id": "c9a150394bb8dd8b",
"type": "comment",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "Отправка данных",
"info": "",
"x": 150,
"y": 120,
"wires": []
},
{
"id": "9f9472d611ecf562",
"type": "comment",
"z": "2f52923ccb63864b",
"g": "0c3ab2711ef23cd5",
"name": "Прием данных",
"info": "",
"x": 140,
"y": 520,
"wires": []
},
{
"id": "229f643b2e4dc980",
"type": "serial out",
"z": "2f52923ccb63864b",
"g": "bb3960f039b0d5d9",
"name": "",
"serial": "baa0d15198c00a18",
"x": 660,
"y": 180,
"wires": []
},
{
"id": "afb27fbd0a803a11",
"type": "ui_group",
"name": "Участник 1",
"tab": "af8825e119b68714",
"order": 1,
"disp": true,
"width": "11",
"collapse": false,
"className": ""
},
{
"id": "baa0d15198c00a18",
"type": "serial-port",
"name": "",
"serialport": "/dev/ttyUSB3",
"serialbaud": "115200",
"databits": "8",
"parity": "none",
"stopbits": "1",
"waitfor": "",
"dtr": "none",
"rts": "none",
"cts": "none",
"dsr": "none",
"newline": "500",
"bin": "false",
"out": "interbyte",
"addchar": "\\r\\n",
"responsetimeout": "2000"
},
{
"id": "af8825e119b68714",
"type": "ui_tab",
"name": "Обмен сообщениями 1",
"icon": "dashboard",
"order": 1,
"disabled": false,
"hidden": false
}
]
© Habrahabr.ru