├── AndroidStudio ├── USBRFMApp │ ├── .gitignore │ ├── .idea │ │ ├── codeStyles │ │ │ └── Project.xml │ │ ├── gradle.xml │ │ ├── jarRepositories.xml │ │ ├── misc.xml │ │ ├── runConfigurations.xml │ │ └── vcs.xml │ ├── app │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ ├── release │ │ │ ├── app-release.apk │ │ │ └── output-metadata.json │ │ └── src │ │ │ ├── androidTest │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── pulsartronic │ │ │ │ └── usbrfmapp │ │ │ │ └── ExampleInstrumentedTest.java │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── assets │ │ │ │ ├── USBRFMApp │ │ │ │ │ ├── USBRFMApp.css │ │ │ │ │ ├── USBRFMApp.js │ │ │ │ │ ├── app │ │ │ │ │ │ ├── App.css │ │ │ │ │ │ ├── App.js │ │ │ │ │ │ └── settings │ │ │ │ │ │ │ ├── Settings.css │ │ │ │ │ │ │ └── Settings.js │ │ │ │ │ └── connection │ │ │ │ │ │ ├── SerialConnection.css │ │ │ │ │ │ └── SerialConnection.js │ │ │ │ ├── [cdnode] │ │ │ │ │ ├── Node.js │ │ │ │ │ └── RootNode.js │ │ │ │ ├── [cdos] │ │ │ │ │ └── cdos.js │ │ │ │ ├── [cdrfm] │ │ │ │ │ ├── RFM.css │ │ │ │ │ └── RFM.js │ │ │ │ ├── [chat] │ │ │ │ │ ├── Chat.css │ │ │ │ │ ├── Chat.js │ │ │ │ │ └── chatbox │ │ │ │ │ │ ├── ChatBox.css │ │ │ │ │ │ ├── ChatBox.js │ │ │ │ │ │ ├── input │ │ │ │ │ │ ├── ChatInput.css │ │ │ │ │ │ └── ChatInput.js │ │ │ │ │ │ └── messagebox │ │ │ │ │ │ ├── MessageBox.css │ │ │ │ │ │ ├── MessageBox.js │ │ │ │ │ │ └── messagerow │ │ │ │ │ │ ├── MessageRow.css │ │ │ │ │ │ ├── MessageRow.js │ │ │ │ │ │ └── bubble │ │ │ │ │ │ ├── Bubble.css │ │ │ │ │ │ ├── Bubble.js │ │ │ │ │ │ ├── message │ │ │ │ │ │ ├── Message.css │ │ │ │ │ │ └── Message.js │ │ │ │ │ │ └── name │ │ │ │ │ │ ├── Name.css │ │ │ │ │ │ └── Name.js │ │ │ │ ├── [console] │ │ │ │ │ ├── Console.css │ │ │ │ │ └── Console.js │ │ │ │ ├── [crypto] │ │ │ │ │ ├── AESM.js │ │ │ │ │ ├── aes.js │ │ │ │ │ ├── seedrandom.js │ │ │ │ │ └── sha256.js │ │ │ │ ├── [inputs] │ │ │ │ │ ├── inputs.css │ │ │ │ │ ├── inputs.js │ │ │ │ │ ├── pins.js │ │ │ │ │ └── styles.css │ │ │ │ ├── [iserial] │ │ │ │ │ ├── ISerial.js │ │ │ │ │ ├── WebAndroidSerial.js │ │ │ │ │ └── WebSerial.js │ │ │ │ ├── [serialport] │ │ │ │ │ ├── SerialPort.css │ │ │ │ │ └── SerialPort.js │ │ │ │ ├── [std] │ │ │ │ │ └── std.js │ │ │ │ └── index.html │ │ │ ├── ic_launcher-playstore.png │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── pulsartronic │ │ │ │ │ └── usbrfmapp │ │ │ │ │ └── USBRFMApp.java │ │ │ └── res │ │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ ├── drawable │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ ├── layout │ │ │ │ └── activity_main.xml │ │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── values │ │ │ │ ├── colors.xml │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ │ └── xml │ │ │ │ └── device_filter.xml │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── pulsartronic │ │ │ └── usbrfmapp │ │ │ └── ExampleUnitTest.java │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle └── USBRFMAppKeystore.jks ├── ArduinoIDE └── USBRFMApp │ ├── USBRFMApp │ ├── App.cpp │ ├── Defaults.h │ ├── USBRFMApp.cpp │ ├── USBRFMApp.h │ └── USBRFMApp.ino │ └── libraries │ ├── CDS │ ├── Array.cpp │ ├── CDS.h │ ├── DataBuffer.cpp │ ├── DynamicBuffer.cpp │ ├── EEPROMBuffer.cpp │ ├── Element.cpp │ ├── Iterator.cpp │ ├── Number.cpp │ ├── Object.cpp │ ├── PROGMEMBuffer.cpp │ ├── StaticBuffer.cpp │ └── StreamBuffer.cpp │ ├── DataChannel │ ├── DataChannel.cpp │ ├── DataChannel.h │ └── Handler.cpp │ ├── DataStructure │ ├── DS.h │ └── KeyValueMap.h │ ├── Node │ ├── Node.cpp │ ├── Node.h │ ├── RootNode.cpp │ └── RootNode.h │ ├── RFM │ ├── Channel.cpp │ ├── RFM.cpp │ └── RFM.h │ ├── SerialPort │ ├── AVRSerialPort.cpp │ ├── Channel.cpp │ ├── ESPSerialPort.cpp │ ├── SerialPort.cpp │ └── SerialPort.h │ └── arduino-LoRa-master │ ├── API.md │ ├── LICENSE │ ├── README.md │ ├── examples │ ├── LoRaDumpRegisters │ │ └── LoRaDumpRegisters.ino │ ├── LoRaDuplex │ │ └── LoRaDuplex.ino │ ├── LoRaDuplexCallback │ │ └── LoRaDuplexCallback.ino │ ├── LoRaReceiver │ │ └── LoRaReceiver.ino │ ├── LoRaReceiverCallback │ │ └── LoRaReceiverCallback.ino │ ├── LoRaSender │ │ └── LoRaSender.ino │ ├── LoRaSenderNonBlocking │ │ └── LoRaSenderNonBlocking.ino │ ├── LoRaSenderNonBlockingCallback │ │ └── LoRaSenderNonBlockingCallback.ino │ ├── LoRaSetSpread │ │ └── LoRaSetSpread.ino │ ├── LoRaSetSyncWord │ │ └── LoRaSetSyncWord.ino │ ├── LoRaSimpleGateway │ │ └── LoRaSimpleGateway.ino │ └── LoRaSimpleNode │ │ └── LoRaSimpleNode.ino │ ├── issue_template.md │ ├── keywords.txt │ ├── library.properties │ └── src │ ├── LoRa.cpp │ └── LoRa.h ├── LICENSE ├── README.md └── USBRFMApp.v1.apk /AndroidStudio/USBRFMApp/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 30 5 | buildToolsVersion "30.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.pulsartronic.usbrfmapp" 9 | minSdkVersion 16 10 | targetSdkVersion 30 11 | versionCode 2 12 | versionName "2.0" 13 | 14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | compileOptions { 24 | sourceCompatibility JavaVersion.VERSION_1_8 25 | targetCompatibility JavaVersion.VERSION_1_8 26 | } 27 | } 28 | 29 | dependencies { 30 | implementation fileTree(dir: "libs", include: ["*.jar"]) 31 | implementation 'androidx.appcompat:appcompat:1.2.0' 32 | implementation 'androidx.constraintlayout:constraintlayout:2.0.2' 33 | implementation 'com.github.felHR85:UsbSerial:6.1.0' 34 | testImplementation 'junit:junit:4.12' 35 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 36 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 37 | 38 | } -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/release/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/app/release/app-release.apk -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/release/output-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "artifactType": { 4 | "type": "APK", 5 | "kind": "Directory" 6 | }, 7 | "applicationId": "com.pulsartronic.usbrfmapp", 8 | "variantName": "release", 9 | "elements": [ 10 | { 11 | "type": "SINGLE", 12 | "filters": [], 13 | "properties": [], 14 | "versionCode": 2, 15 | "versionName": "2.0", 16 | "enabled": true, 17 | "outputFile": "app-release.apk" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/androidTest/java/com/pulsartronic/usbrfmapp/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.pulsartronic.usbrfmapp; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.pulsartronic.usbrfmapp", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/USBRFMApp/USBRFMApp.css: -------------------------------------------------------------------------------- 1 | div.USBRFMApp { 2 | width: 100%; 3 | user-select: none; 4 | -moz-user-select: none; 5 | -webkit-user-select: none; 6 | -ms-user-select: none; 7 | } 8 | 9 | div.USBRFMApp div.Vapp { 10 | width: 100%; 11 | } 12 | 13 | div.USBRFMApp div.Vapp div.Nodes { 14 | width: 100%; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/USBRFMApp/USBRFMApp.js: -------------------------------------------------------------------------------- 1 | let TSTMP_OPTIONS = {year:'numeric',month:'numeric',day:'numeric',hour:'numeric',minute:'numeric',second:'numeric'}; 2 | let TIC_OPTIONS = {year:'numeric',month:'numeric',day:'numeric',hour:'numeric',minute:'numeric'}; 3 | 4 | /////////////////////////////////////////////////////////////////////////////////// 5 | // USBRFMApp 6 | let USBRFMApp = function(parent) { 7 | RootNode.call(this, parent, 'root'); 8 | 9 | this.tag = document.createElement('div'); 10 | this.tag.className = 'Configuration USBRFMApp'; 11 | 12 | this.connection = new SerialConnection(this); 13 | this.tag.append(this.connection.tag); 14 | this.connection.onConnected = this.onConnected.bind(this); 15 | this.connection.onDisconnected = this.onDisconnected.bind(this); 16 | this.connection.onConnectError = this.onConnectError.bind(this); 17 | this.connection.onCommand = this.oncommand.bind(this); 18 | 19 | // TODO:: add another divission 20 | this.vapp = document.createElement('div'); 21 | this.vapp.className = 'Vapp'; 22 | this.tag.append(this.vapp); 23 | 24 | this.tabs = new Tabs(this); 25 | this.vapp.append(this.tabs.tag); 26 | 27 | // ////////////////////////////////////////////////////////// 28 | // Visual division 29 | this.vnodes = document.createElement('div'); 30 | this.vnodes.className = 'Nodes'; 31 | this.vapp.append(this.vnodes); 32 | 33 | this.rfm = new RFM(this, 'rfm'); 34 | this.addNode(this.rfm); 35 | this.tabs.addTab(this.rfm.tag, 'RFM', false); 36 | 37 | this.serial = new SerialPort(this, 'serial'); 38 | this.addNode(this.serial); 39 | this.tabs.addTab(this.serial.tag, 'Serial', false); 40 | this.serial.baudrate.input.input.disabled = true; 41 | this.serial.config.input.input.disabled = true; 42 | this.serial.invert.input.input.disabled = true; 43 | this.serial.bsize.input.input.disabled = true; 44 | this.serial.rx.input.input.disabled = true; 45 | this.serial.tx.input.input.disabled = true; 46 | 47 | this.app = new App(this, 'app'); 48 | this.addNode(this.app); 49 | this.tabs.addTab(this.app.tag, 'App', true); 50 | 51 | this.savebutton = document.createElement('div'); 52 | this.savebutton.className = 'Button'; 53 | this.savebutton.textContent = 'Save Settings'; 54 | this.vapp.append(this.savebutton); 55 | this.savebutton.onclick = this.saveClicked.bind(this); 56 | 57 | this.separator = document.createElement('div'); 58 | this.separator.className = 'Separator'; 59 | this.tag.append(this.separator); 60 | 61 | this.explanation = document.createElement('div'); 62 | this.explanation.className = 'TextContent'; 63 | this.explanation.textContent = 'Module console log:'; 64 | this.tag.append(this.explanation); 65 | 66 | this.console = new Console(); 67 | this.tag.append(this.console.tag); 68 | 69 | this.messages = new Messages(this); 70 | this.messages.tag.style['display'] = 'none'; 71 | this.tag.append(this.messages.tag); 72 | 73 | this.tcallback = null; 74 | this.errors = 0; 75 | }; 76 | 77 | for (let i in RootNode.prototype) 78 | USBRFMApp.prototype[i] = RootNode.prototype[i]; 79 | 80 | USBRFMApp.prototype.init = function() { 81 | RootNode.prototype.init.call(this); 82 | this.connection.init(); 83 | this.rfm.init(); 84 | this.serial.init(); 85 | this.app.init(); 86 | this.showConnection(true); 87 | }; 88 | 89 | USBRFMApp.prototype.addNode = function(node) { 90 | this.nodes.push(node); 91 | this.vnodes.append(node.tag); 92 | }; 93 | 94 | USBRFMApp.prototype.showConnection = function(show) { 95 | this.connection.tag.style['display'] = show ? '' : 'none'; 96 | this.vapp.style['display'] = !show ? '' : 'none'; 97 | }; 98 | 99 | USBRFMApp.prototype.setOpacity = function(opacity) { 100 | this.connection.tag.style['opacity'] = opacity; 101 | this.vapp.style['opacity'] = opacity; 102 | }; 103 | 104 | USBRFMApp.prototype.onConnected = function() { 105 | this.showConnection(false); 106 | this.messages.showWaiting(); 107 | 108 | let tag = this.tabs.selectedTag(); 109 | this.tabClicked(tag); 110 | }; 111 | 112 | USBRFMApp.prototype.onDisconnected = function() { 113 | this.showConnection(true); 114 | this.log("USB disconnected"); 115 | for (let i in this.nodes) { 116 | let node = this.nodes[i]; 117 | node.loaded = false; 118 | } 119 | }; 120 | 121 | USBRFMApp.prototype.onConnectError = function(e) { 122 | console.log(e); 123 | this.showConnection(true); 124 | }; 125 | 126 | USBRFMApp.prototype.tabClicked = function(tag) { 127 | let node = tag.node; 128 | if (!node.loaded) { 129 | this.messages.showWaiting(); 130 | let command = new CDObject(); 131 | let cnode = new CDObject(); 132 | let state = new CDObject(); 133 | cnode.set("state", state); 134 | command.set(node.name, cnode); 135 | this.command(command); 136 | } 137 | }; 138 | 139 | USBRFMApp.prototype.oncommand = function(command) { 140 | console.log("--------------------------------------------------------------------"); 141 | console.log("Receiving from USB/Serial port"); 142 | console.log(CDOS.stringify(command)); 143 | Node.prototype.oncommand.call(this, command); 144 | this.messages.hideWaiting(); 145 | clearTimeout(this.tcallback); 146 | this.errors = 0; 147 | }; 148 | 149 | USBRFMApp.prototype.command = function(command) { 150 | console.log("--------------------------------------------------------------------"); 151 | console.log("Sending to USB/Serial port"); 152 | console.log(CDOS.stringify(command)); 153 | this.connection.send(command); 154 | this.tcallback = setTimeout(this.timedout.bind(this, command), 2000); 155 | }; 156 | 157 | USBRFMApp.prototype.timedout = function(command) { 158 | clearTimeout(this.tcallback); 159 | this.errors += 1; 160 | if (1 < this.errors) { 161 | this.command(command); 162 | } else { 163 | this.messages.showMessage("Connection error ..."); 164 | this.showConnection(true); 165 | this.connection.close(); 166 | } 167 | }; 168 | 169 | USBRFMApp.prototype.showMessage = function(message, html = false) { 170 | this.messages.showMessage(message, html); 171 | }; 172 | 173 | USBRFMApp.prototype.saveClicked = function() { 174 | let hasChanges = true;//this.hasChanges(); 175 | if (hasChanges) { 176 | let valid = this.validate(); 177 | if (valid) { 178 | this.messages.showWaiting(); 179 | let command = new CDObject(); 180 | this.save(command); 181 | this.command(command); 182 | } 183 | } 184 | }; 185 | 186 | USBRFMApp.prototype.log = function(text) { 187 | var now = new Date(); 188 | let date = now.toLocaleDateString('en-US', TSTMP_OPTIONS); 189 | let line = '[' + date + '] ' + text; 190 | this.console.addTextLine(line); 191 | }; 192 | 193 | // ///////////////////////////////////////////////////////////////////////////////////////// 194 | // Program entry point 195 | window.onload = () => { 196 | let config = document.getElementById('config'); 197 | window.app = new USBRFMApp(); 198 | config.append(window.app.tag); 199 | window.app.init(); 200 | }; 201 | 202 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/USBRFMApp/app/App.css: -------------------------------------------------------------------------------- 1 | div.App { 2 | width: 100%; 3 | margin-top: 1em; 4 | min-height: calc(100vh - 25em); 5 | } 6 | 7 | div.App div.MessageBox { 8 | height: calc(100vh - 16.5em); 9 | } 10 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/USBRFMApp/app/App.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This is an example web app which reads/writes bytes from/to a LoRa device 3 | * 4 | * If you are no going to use the chat system, you can safely delete 5 | * All code marked here as "CHAT specific code" 6 | * [chat] and USBRFMApp/App/settings folders 7 | */ 8 | /////////////////////////////////////////////////////////////////////////////////// 9 | // App 10 | let App = function(parent, name) { 11 | Node.call(this, parent, name); 12 | 13 | // ////////////////////////////////////////////////////////////// 14 | // this is the HTML tag you can append children to 15 | this.tag = document.createElement('div'); 16 | this.tag.className = 'App'; 17 | this.tag.node = this; 18 | 19 | // ////////////////////////////////////////////////////////////// 20 | // CHAT specific code 21 | this.tabs = new Tabs(this); 22 | this.tag.append(this.tabs.tag); 23 | this.settings = new Settings(this); 24 | this.tag.append(this.settings.tag); 25 | this.tabs.addTab(this.settings.tag, 'settings', false); 26 | this.chat = new Chat(this); 27 | this.chat.tag.style['display'] = 'none'; 28 | this.tag.append(this.chat.tag); 29 | this.tabs.addTab(this.chat.tag, 'chat', true); 30 | this.chat.onuserinput = this.onuserinput.bind(this); 31 | this.chat.chatbox.input.input.maxLength = 128; 32 | // ////////////////////////////////////////////////////////////// 33 | }; 34 | 35 | // Inheritance 36 | for (let i in Node.prototype) 37 | App.prototype[i] = Node.prototype[i]; 38 | 39 | 40 | /* 41 | * This is called once all initial html elements are appended to the document 42 | */ 43 | App.prototype.init = function() { 44 | // ////////////////////////////////////////////////////////////// 45 | // CHAT specific code 46 | this.settings.init(); 47 | let message = {}; 48 | message.own = true; 49 | message.from = this.settings.user.value(); 50 | message.text = 'USB RFM App v1.0 - chat room'; 51 | this.chat.onmessage(message); 52 | // ////////////////////////////////////////////////////////////// 53 | }; 54 | 55 | 56 | /* 57 | * This is called from the arduino, and it means that communication is possible 58 | */ 59 | App.prototype.state = function(params) { 60 | this.loaded = true; 61 | }; 62 | 63 | 64 | /* 65 | * This is called when the user clicks the send button 66 | */ 67 | App.prototype.onuserinput = function(text) { 68 | // ////////////////////////////////////////////////////////////// 69 | // CHAT specific code 70 | let message = {}; 71 | message.own = true; 72 | message.from = this.settings.user.value(); 73 | message.text = text; 74 | this.chat.onmessage(message); 75 | let smessage = new CDObject(); 76 | let from = new CDNumber(message.from); 77 | smessage.set('from', from); 78 | let stext = new CDNumber(text); 79 | smessage.set('text', stext); 80 | let length = smessage.calculateLength(); 81 | let buffer = new Uint8Array(length); 82 | let iterator = new CDIterator(buffer, buffer.length); 83 | smessage.serialize(iterator); 84 | // //////////////////////////////////////////////////////////////////////// 85 | 86 | 87 | 88 | 89 | // //////////////////////////////////////////////////////////////////////// 90 | // these are the raw bytes the RFM module is going to emit, change it. 91 | // Do something like 92 | // let ebuffer = new Uint8Array([0x21, 0x43 ... your values]); 93 | let ebuffer = this.settings.aesm.encrypt(buffer); 94 | // //////////////////////////////////////////////////////////////////////// 95 | // send data ---> AndroidApp -> USB -> Arduino -> LoRa 96 | let command = new CDObject(); 97 | let send = command.newObject('send'); 98 | let data = send.newNumber('data'); 99 | data.setBuffer(ebuffer); 100 | this.command(command); 101 | }; 102 | 103 | /* 104 | * This is called in response to a transmission 105 | */ 106 | App.prototype.sent = function(params) { 107 | let totalElement = params.get('total'); 108 | let total = totalElement.int(); 109 | this.parent.log(`TX ${total} bytes`); 110 | }; 111 | 112 | /* 113 | + This is called when the RFM module receives data 114 | */ 115 | App.prototype.ondata = function(params) { 116 | try { 117 | let dataElement = params.get("data"); 118 | let rssiElement = params.get('rssi'); // Received Signal Strength Indicator 119 | let snrElement = params.get('snr'); // Signal-to-noise ratio 120 | let pfeElement = params.get('pfe'); // Packet Frequency Error 121 | 122 | // //////////////////////////////////////////////////////////////////////// 123 | // these are the raw bytes the RFM module received, make somethig with them 124 | let ebuffer = dataElement.bytes; 125 | // extra information about the received packet 126 | let rssi = rssiElement.int(); 127 | let snr = snrElement.float(); 128 | let pfe = pfeElement.int(); 129 | this.parent.log(`RX: ${ebuffer.length} bytes, RSSI: ${rssi}db, , PFE: ${pfe}, SNR: ${snr}`); 130 | // //////////////////////////////////////////////////////////////////////// 131 | 132 | // ////////////////////////////////////////////////////////////// 133 | // CHAT specific code 134 | let buffer = this.settings.aesm.decrypt(ebuffer); 135 | let iterator = new CDIterator(buffer, buffer.length); 136 | let valid = iterator.valid(); 137 | if (valid) { 138 | let smessage = iterator.nextElement(); 139 | let fromElement = smessage.get('from'); 140 | let textElement = smessage.get('text'); 141 | let message = {}; 142 | message.own = false; 143 | message.from = fromElement.string(); 144 | message.text = textElement.string(); 145 | message.rssi = rssiElement.int(); 146 | this.chat.onmessage(message); 147 | } 148 | // ////////////////////////////////////////////////////////////// 149 | } catch(e) { 150 | console.log(e); 151 | } 152 | }; 153 | 154 | 155 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/USBRFMApp/app/settings/Settings.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/app/src/main/assets/USBRFMApp/app/settings/Settings.css -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/USBRFMApp/app/settings/Settings.js: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////// 2 | // Settings 3 | let Settings = function(parent) { 4 | this.parent = parent; 5 | 6 | this.tag = document.createElement('div'); 7 | this.tag.className = 'Settings'; 8 | 9 | this.title = document.createElement('div'); 10 | this.title.className = 'Title'; 11 | this.title.textContent = 'Room settings'; 12 | this.tag.append(this.title); 13 | 14 | this.separator = document.createElement('div'); 15 | this.separator.className = 'Separator'; 16 | this.tag.append(this.separator); 17 | 18 | this.roomid = new InputRow(this, 'room', 'text', ''); 19 | this.tag.append(this.roomid.tag); 20 | this.roomid.pong('default'); 21 | this.roomid.onchange = this.onDataChanged.bind(this); 22 | 23 | this.user = new InputRow(this, 'username', 'text', ''); 24 | this.tag.append(this.user.tag); 25 | this.user.pong('no name'); 26 | this.user.onchange = this.onDataChanged.bind(this); 27 | 28 | this.aesm = null; 29 | }; 30 | 31 | Settings.prototype.init = function() { 32 | let settings = {}; 33 | settings.app = {}; 34 | settings.app.user = this.user.value(); 35 | settings.app.roomid = this.roomid.value(); 36 | 37 | try { 38 | let usbRFMAppSTR = localStorage.getItem('USBRFMApp') || '{}'; 39 | let savedSettings = JSON.parse(usbRFMAppSTR); 40 | savedSettings.app = savedSettings.app || {}; 41 | savedSettings.app.roomid = savedSettings.app.roomid || `default`; 42 | savedSettings.app.user = savedSettings.app.user || `user ${Math.floor(100000 * Math.random())}`; 43 | let USBRFMApp = JSON.stringify(savedSettings); 44 | localStorage.setItem('USBRFMApp', savedSettings); 45 | settings = savedSettings; 46 | } catch(e) { 47 | // window.app.rfm.console.addTextLine(e); 48 | } 49 | 50 | this.roomid.pong(settings.app.roomid); 51 | this.user.pong(settings.app.user); 52 | 53 | let key = Sha256.hash(settings.app.roomid); 54 | this.aesm = new AESM(key); 55 | }; 56 | 57 | Settings.prototype.onDataChanged = function() { 58 | let settings = {}; 59 | settings.app = {}; 60 | settings.app.user = this.user.value(); 61 | settings.app.roomid = this.roomid.value(); 62 | 63 | try { 64 | let settingsSTR = localStorage.getItem('USBRFMApp'); 65 | let savedSettings = JSON.parse(settingsSTR); 66 | savedSettings.app.roomid = settings.app.roomid; 67 | savedSettings.app.user = settings.app.user; 68 | settings = savedSettings; 69 | } catch(e) { 70 | 71 | } 72 | 73 | let key = Sha256.hash(settings.app.roomid); 74 | this.aesm = new AESM(key); 75 | 76 | try { 77 | let USBRFMApp = JSON.stringify(settings); 78 | localStorage.setItem('USBRFMApp', USBRFMApp); 79 | } catch(e) { 80 | 81 | } 82 | }; 83 | 84 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/USBRFMApp/connection/SerialConnection.css: -------------------------------------------------------------------------------- 1 | div.SerialConnection { 2 | margin-bottom: 3em; 3 | } 4 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/USBRFMApp/connection/SerialConnection.js: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////// 2 | // SerialConnection 3 | let SerialConnection = function(parent) { 4 | this.parent = parent; 5 | 6 | this.tag = document.createElement('div'); 7 | this.tag.className = 'SerialConnection'; 8 | 9 | this.title = document.createElement('div'); 10 | this.title.className = 'Title'; 11 | this.title.textContent = 'Serial connection'; 12 | this.tag.append(this.title); 13 | 14 | this.separator = document.createElement('div'); 15 | this.separator.className = 'Separator'; 16 | this.tag.append(this.separator); 17 | 18 | this.baudrate = new InputRow(this, 'Baudrate', 'select', ''); 19 | this.baudrate.addOptions(SerialPort.SPEEDS); 20 | this.tag.append(this.baudrate.tag); 21 | // this.baudrate.setHelp('This is the baudrate this interface should use to communicate with the device.'); 22 | this.baudrate.pong(9600); 23 | 24 | this.config = new InputRow(this, 'Configuration', 'select', ''); 25 | this.config.addOptions(SerialPort.CONFIG); 26 | this.tag.append(this.config.tag); 27 | // this.config.setHelp('This is the default power the module should emmit with.'); 28 | this.config.pong(3); 29 | 30 | this.connectButton = document.createElement('div'); 31 | this.connectButton.className = 'Button'; 32 | this.connectButton.textContent = 'connect'; 33 | this.connectButton.onclick = this.connect.bind(this); 34 | this.tag.append(this.connectButton); 35 | 36 | if (!navigator.serial) { 37 | this.iserial = new WebAndroidSerial(); 38 | } else { 39 | this.iserial = new WebSerial(); 40 | } 41 | this.iserial.onconnect = this.onconnect.bind(this); 42 | this.iserial.ondisconnect = this.ondisconnect.bind(this); 43 | this.iserial.ondata = this.ondata.bind(this); 44 | this.iserial.onerror = this.onerror.bind(this); 45 | this.iserial.onlog = this.onlog.bind(this); 46 | 47 | this.buffer = new Uint8Array(); 48 | this.rcallback = null; 49 | }; 50 | 51 | SerialConnection.prototype.onConnected = function() {}; 52 | SerialConnection.prototype.onConnectError = function() {}; 53 | SerialConnection.prototype.onDisconnected = function() {}; 54 | SerialConnection.prototype.onCommand = function(command) {}; 55 | 56 | SerialConnection.prototype.init = function() { 57 | try { 58 | let settingsSTR = localStorage.getItem('USBRFMApp'); 59 | let savedSettings = JSON.parse(settingsSTR); 60 | this.baudrate.pong(savedSettings.connection.baudrate); 61 | this.config.pong(savedSettings.connection.config); 62 | } catch(e) { 63 | console.log(e); 64 | } 65 | }; 66 | 67 | SerialConnection.prototype.connect = async function() { 68 | let options = {}; 69 | options.baudrate = this.baudrate.value()|0; 70 | options.config = this.config.value()|0; 71 | 72 | try { 73 | let settingsSTR = localStorage.getItem('USBRFMApp') || '{}'; 74 | let savedSettings = JSON.parse(settingsSTR); 75 | savedSettings.connection = savedSettings.connection || {}; 76 | savedSettings.connection.baudrate = options.baudrate; 77 | savedSettings.connection.config = options.config; 78 | let usbRFMApp = JSON.stringify(savedSettings); 79 | localStorage.setItem('USBRFMApp', usbRFMApp); 80 | } catch(e) { 81 | console.log(e); 82 | } 83 | 84 | await this.iserial.open(options); 85 | }; 86 | 87 | SerialConnection.prototype.onconnect = function() { 88 | this.onConnected(); 89 | }; 90 | 91 | SerialConnection.prototype.ondisconnect = function() { 92 | this.onDisconnected(); 93 | }; 94 | 95 | SerialConnection.prototype.onerror = function(e) { 96 | this.onConnectError(e); 97 | }; 98 | 99 | SerialConnection.prototype.send = function(command) { 100 | try { 101 | let size = command.calculateLength(); 102 | let ui8buffer = new Uint8Array(size); 103 | let iterator = new CDIterator(ui8buffer, size); 104 | command.serialize(iterator); 105 | this.iserial.send(ui8buffer); 106 | } catch(e) { 107 | this.onlog(e); 108 | } 109 | }; 110 | 111 | SerialConnection.prototype.ondata = function(bytes) { 112 | clearTimeout(this.rcallback); 113 | this.rcallback = setTimeout(() => {this.buffer = new Uint8Array();}, 2000); 114 | 115 | let newbuffer = new Uint8Array(this.buffer.length + bytes.length); 116 | newbuffer.set(this.buffer, 0); 117 | newbuffer.set(bytes, this.buffer.length); 118 | let iterator = new CDIterator(newbuffer, newbuffer.length); 119 | let valid = iterator.valid(); 120 | //console.log(bytes); 121 | if (valid) { 122 | let command = iterator.nextElement(); 123 | this.buffer = new Uint8Array(); 124 | clearTimeout(this.rcallback); 125 | this.onCommand(command); 126 | } else { 127 | this.buffer = newbuffer; 128 | } 129 | }; 130 | 131 | SerialConnection.prototype.onlog = function(text) { 132 | this.parent.log(text); 133 | }; 134 | 135 | SerialConnection.prototype.close = function() { 136 | this.iserial.close(); 137 | }; 138 | 139 | 140 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[cdnode]/Node.js: -------------------------------------------------------------------------------- 1 | let Node = function(parent, name) { 2 | this.parent = parent; 3 | this.name = name; 4 | 5 | this.nodes = []; 6 | }; 7 | 8 | Node.prototype.name = ''; 9 | 10 | Node.prototype.addNode = function(node) { 11 | this.tag.append(node.tag); 12 | this.nodes.push(node); 13 | }; 14 | 15 | Node.prototype.oncommand = function(command) { 16 | // we want parent's methods to be called before children's 17 | for (let i in command.keys) { 18 | let key = command.keys[i]; 19 | let attribute = this[i]; 20 | if ('function' == typeof attribute) { 21 | let mparams = key.value; 22 | attribute.call(this, mparams); 23 | } 24 | } 25 | 26 | for (let i in command.keys) { 27 | let key = command.keys[i]; 28 | let attribute = this[i]; 29 | if ('object' == typeof attribute) { 30 | if (attribute.oncommand) { 31 | let icommand = key.value; 32 | attribute.oncommand(icommand); 33 | } else { 34 | console.log(`Unimplemented ${i}.oncommand(command)`); 35 | } 36 | } else if ('function' != typeof attribute) { 37 | console.log(`Unknown property ${this.name}.${i}`); 38 | } 39 | } 40 | }; 41 | 42 | Node.prototype.stateCommand = function() { 43 | let command = new CDObject(); 44 | let stateElement = new CDObject(); 45 | command.set('state', stateElement); 46 | return command; 47 | }; 48 | 49 | // <-- 50 | Node.prototype.command = function(command) { 51 | let pcommand = new CDObject(); 52 | pcommand.set(this.name, command); 53 | this.parent.command(pcommand); 54 | }; 55 | 56 | Node.prototype.log = function(params) { 57 | console.log(this.name + ' : ' + params.text); 58 | }; 59 | 60 | // call generation ... 61 | Node.prototype.hasChanges = function() { 62 | let hasChanges = this.isChanged(); 63 | for (let node of this.nodes) { 64 | hasChanges = hasChanges || node.hasChanges(); 65 | } 66 | return hasChanges; 67 | }; 68 | 69 | Node.prototype.isChanged = function() { 70 | return false; 71 | }; 72 | 73 | Node.prototype.save = function(command) { 74 | for (let key in this.nodes) { 75 | let node = this.nodes[key]; 76 | let hasChanges = node.hasChanges(); 77 | if (hasChanges) { 78 | let icommand = command.get(node.name); 79 | if (!icommand) { 80 | icommand = new CDObject(); 81 | command.set(node.name, icommand); 82 | } 83 | node.save(icommand); 84 | } 85 | } 86 | }; 87 | 88 | Node.prototype.validate = function() { 89 | let valid = true; 90 | for (let key in this.nodes) { 91 | let node = this.nodes[key]; 92 | valid = node.validate() && valid; 93 | } 94 | return valid; 95 | }; 96 | 97 | Node.prototype.showMessage = function(message, html = false) { 98 | this.parent.showMessage(message, html); 99 | }; 100 | 101 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[cdnode]/RootNode.js: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////// 2 | // RootNode 3 | let RootNode = function(parent, name) { 4 | Node.call(this, parent, name); 5 | 6 | this.aes = null; 7 | this.jlid = null; 8 | this.syncID = 0; 9 | this.errors = 0; 10 | }; 11 | 12 | for (let i in Node.prototype) 13 | RootNode.prototype[i] = Node.prototype[i]; 14 | 15 | RootNode.prototype.onLoggedin = function() {}; 16 | RootNode.prototype.onConnected = function() {}; 17 | RootNode.prototype.onLoginError = function() {}; 18 | RootNode.prototype.onSynced = function() {}; 19 | RootNode.prototype.onErrorSyncing = function() {}; 20 | // RootNode.prototype.oncommand = function(command) {}; 21 | RootNode.prototype.onLoggedOut = function() {}; 22 | RootNode.prototype.reconnectTimeout = null; 23 | 24 | RootNode.prototype.init = function() { 25 | // this.requestJLID(); 26 | }; 27 | 28 | RootNode.prototype.setJLID = function(jlid) { 29 | this.jlid = jlid; 30 | this.syncID = this.jlid.l - Date.now() + 1; 31 | }; 32 | 33 | RootNode.prototype.getJLID = function() { 34 | let jlid = {}; 35 | jlid.b = this.jlid.b; 36 | jlid.l = this.syncID + Date.now(); 37 | return jlid; 38 | }; 39 | 40 | RootNode.prototype.requestJLID = function() { 41 | //this.sendRequest('/s', '', this.onjlid.bind(this)); 42 | }; 43 | 44 | RootNode.prototype.onjlid = function(response) { 45 | if (!response.error) { 46 | let jlid = JSON.parse(response); 47 | this.setJLID(jlid); 48 | this.onSynced(); 49 | } else { 50 | console.log('error syncing, trying again ...'); 51 | console.log(response); 52 | setTimeout(this.requestJLID.bind(this), 2 * 1000); 53 | } 54 | }; 55 | 56 | RootNode.prototype.okClicked = function() { 57 | if (this.jlid) { 58 | if (this.changeButton.showing) { 59 | this.change(); 60 | } else { 61 | this.login(); 62 | } 63 | } 64 | }; 65 | 66 | RootNode.prototype.signin = function(user, pass) { 67 | let hash = Sha256.hash(user + pass); 68 | this.hsignin(hash); 69 | }; 70 | 71 | RootNode.prototype.hsignin = function(hash) { 72 | this.aesm = new AESM(hash); 73 | this.connection.init(); 74 | // this.httpCommand({'login':{}}, this.loggedin.bind(this)); 75 | }; 76 | 77 | RootNode.prototype.change = function(user, pass, newUser, newPass) { 78 | let hash = Sha256.hash(user + pass); 79 | this.aesm = new AESM(hash); 80 | 81 | let newHash = Sha256.hash(newUser + newPass); 82 | let newKey = newHash.b16ToAB().toB64(); 83 | 84 | let params = {}; 85 | params.key = newKey; 86 | 87 | this.httpCommand({'change':params}, this.loggedin.bind(this)); 88 | this.aesm = new AESM(newHash); 89 | }; 90 | 91 | RootNode.prototype.loggedin = function(response) { 92 | try { 93 | let dataSTR = this.aesm.decrypt(response); 94 | console.log(dataSTR); 95 | let commands = JSON.parse(dataSTR); 96 | switch(commands[0].error) { 97 | case 1: 98 | this.setJLID(commands[0].jlid); 99 | this.onLoginError(); 100 | break; 101 | default: 102 | this.wport = commands[0].wport; 103 | this.onLoggedin(commands[0]); 104 | this.connect(); 105 | break; 106 | } 107 | } catch(e) { 108 | this.onLoginError(); 109 | console.error(e, e.stack); 110 | } 111 | }; 112 | 113 | RootNode.prototype.httpCommand = async function(params, callback) { 114 | let command = {}; 115 | command.id = this.getJLID(); 116 | command.p = params; 117 | let commandSTR = JSON.stringify(command); 118 | let edata = this.aesm.encrypt(commandSTR); 119 | this.sendRequest('/u', edata, callback); 120 | }; 121 | 122 | RootNode.prototype.sendRequest = function(path, data = '', callback) { 123 | let encodedData = encodeURIComponent(data); 124 | let request = new XMLHttpRequest(); 125 | request.open('GET', `http://${this.host}:${this.hport}${path}?d=${encodedData}`); 126 | request.onreadystatechange = () => { 127 | if (4 == request.readyState) { 128 | if (200 == request.status) { 129 | try { 130 | // let response = JSON.parse(request.responseText); 131 | callback(request.responseText); 132 | } catch(e) { 133 | let response = {}; 134 | response.error = 4; 135 | response.cause = e; 136 | callback(response); 137 | } 138 | } 139 | } 140 | }; 141 | 142 | request.onerror = (e) => { 143 | console.log('Network error, trying again ...'); 144 | this.errors += 1; 145 | if (5 >= this.errors) { 146 | setTimeout(this.sendRequest.bind(this, path, data, callback), 3 * 1000); 147 | } else { 148 | this.logout(); 149 | } 150 | }; 151 | 152 | request.send(); 153 | }; 154 | 155 | RootNode.prototype.command = function(params) { 156 | console.log(params); 157 | if (this.socket && WebSocket.OPEN == this.socket.readyState) { 158 | let command = {}; 159 | command.id = this.getJLID(); 160 | command.p = params; 161 | let commandSTR = JSON.stringify(command); 162 | let edata = this.aesm.encrypt(commandSTR); 163 | this.socket.send(edata); 164 | } else { 165 | this.httpCommand(params, (responseText) =>{ 166 | try { 167 | let dataSTR = this.aesm.decrypt(responseText); 168 | console.log(dataSTR); 169 | let commands = JSON.parse(dataSTR); 170 | for (let command of commands) { 171 | this.execute(command); 172 | } 173 | } catch(e) { 174 | //this.logout(); 175 | console.error(e, e.stack); 176 | } 177 | }); 178 | } 179 | }; 180 | 181 | RootNode.prototype.userCommand = function(params) { 182 | this.command(params); 183 | }; 184 | 185 | RootNode.prototype.logout = function() { 186 | this.errors = 0; 187 | clearTimeout(this.reconnectTimeout); 188 | this.onLoggedOut(); 189 | try { 190 | if (this.socket) { 191 | this.socket.onclose = () => {}; 192 | this.socket.close(); 193 | } 194 | } catch(e) { 195 | console.error(e, e.stack); 196 | } 197 | }; 198 | 199 | RootNode.prototype.connect = function() { 200 | try { 201 | clearTimeout(this.reconnectTimeout); 202 | this.socket = new WebSocket(`ws://${this.host}:${this.wport}/`, ['arduino']); 203 | this.socket.onopen = this.onopen.bind(this); 204 | this.socket.onerror = this.onerror.bind(this); 205 | this.socket.onmessage = this.onmessage.bind(this); 206 | this.socket.onclose = this.onclose.bind(this); 207 | } catch(e) { 208 | console.error(e, e.stack); 209 | } 210 | }; 211 | 212 | RootNode.prototype.onopen = function() { 213 | //console.log('onopen :::'); 214 | this.onConnected(); 215 | }; 216 | 217 | RootNode.prototype.onerror = function(error) { 218 | //console.log('error :::'); 219 | }; 220 | 221 | RootNode.prototype.onclose = function(e) { 222 | //console.log('onclose :::'); 223 | clearTimeout(this.reconnectTimeout); 224 | this.reconnectTimeout = setTimeout(this.connect.bind(this), 3 * 1000); 225 | }; 226 | 227 | RootNode.prototype.onmessage = function(e) { 228 | try { 229 | let dataSTR = this.aesm.decrypt(e.data); 230 | console.log(dataSTR); 231 | let command = JSON.parse(dataSTR); 232 | this.execute(command); 233 | } catch(e) { 234 | console.error(e, e.stack); 235 | } 236 | }; 237 | 238 | RootNode.prototype.execute = function(command) { 239 | switch(command.error) { 240 | case 1: 241 | this.errors += 1; 242 | if (5 >= this.errors) { 243 | this.setJLID(command.jlid); 244 | console.log('Error on user command, trying again ...'); 245 | setTimeout(this.userCommand.bind(this, command.c), 1000); 246 | } else { 247 | this.logout(); 248 | } 249 | break; 250 | default: 251 | //console.log("RESP:"); 252 | //console.log(dataSTR); 253 | this.errors = 0; 254 | this.oncommand(command); 255 | break; 256 | } 257 | }; 258 | 259 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[cdrfm]/RFM.css: -------------------------------------------------------------------------------- 1 | div.RFM { 2 | width: 100%; 3 | } 4 | 5 | div.RFM div.InputRow div.Name { 6 | width: 38%; 7 | } 8 | 9 | div.RFM div.InputRow div.Input { 10 | width: calc(60% - 1.2em); 11 | } 12 | 13 | div.Boundary input, 14 | div.Boundary { 15 | font-style: italic; 16 | 17 | } 18 | 19 | div.Boundary div.Name { 20 | font-style: italic; 21 | } 22 | 23 | div.Boundary div.Input input.Large { 24 | color: #555; 25 | } 26 | 27 | div.Pins div.InputRow { 28 | width: 50%; 29 | } 30 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/Chat.css: -------------------------------------------------------------------------------- 1 | div.Chat { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/Chat.js: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////// 2 | // Chat 3 | let Chat = function(parent, name) { 4 | Node.call(this, parent, name); 5 | 6 | this.tag = document.createElement('div'); 7 | this.tag.className = 'Chat'; 8 | this.tag.node = this; 9 | 10 | this.chatbox = new ChatBox(); 11 | this.tag.append(this.chatbox.tag); 12 | this.chatbox.onuserinput = this.onuserinput.bind(this); 13 | 14 | this.id = 0; 15 | }; 16 | 17 | // Inheritance 18 | for (let i in Node.prototype) 19 | Chat.prototype[i] = Node.prototype[i]; 20 | 21 | 22 | Chat.prototype.init = function(data) { 23 | 24 | }; 25 | 26 | Chat.prototype.onuserinput = function(text) { 27 | this.parent.onuserinput(text); 28 | }; 29 | 30 | Chat.prototype.onmessage = function(message) { 31 | this.chatbox.onMessage(message); 32 | }; 33 | 34 | Chat.prototype.sent = function(params) { 35 | console.log(CDOS.stringify(params)); 36 | }; 37 | 38 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/ChatBox.css: -------------------------------------------------------------------------------- 1 | div.ChatBox { 2 | width: 100%; 3 | text-align: initial; 4 | } 5 | 6 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/ChatBox.js: -------------------------------------------------------------------------------- 1 | let ChatBox = function(parent) { 2 | this.parent = parent; 3 | 4 | this.tag = document.createElement("div"); 5 | this.tag.className = "ChatBox"; 6 | 7 | this.messageBox = new MessageBox(this); 8 | this.tag.append(this.messageBox.tag); 9 | 10 | this.input = new ChatInput(this); 11 | this.tag.append(this.input.tag); 12 | 13 | this.onuserinput = async () => {}; 14 | }; 15 | 16 | ChatBox.prototype.userInputReady = async function(text) { 17 | this.input.set(""); 18 | this.input.enable(false); 19 | await this.onuserinput(text); 20 | this.input.enable(true); 21 | this.input.input.focus(); 22 | }; 23 | 24 | ChatBox.prototype.onMessage = function(message) { 25 | this.messageBox.add(message) 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/input/ChatInput.css: -------------------------------------------------------------------------------- 1 | div.ChatInput { 2 | position: relative; 3 | display: flex; 4 | width: 100%; 5 | } 6 | 7 | div.ChatInput input { 8 | position: relative; 9 | display: inline-block; 10 | width: calc(96% - 4px - 3.5em); 11 | margin: 0.1em 1%; 12 | padding: 0.25em 1%; 13 | border: 1px solid #CCC; 14 | border-radius: 2048px; 15 | } 16 | 17 | 18 | div.ChatInput div.SendButton { 19 | display: flex; 20 | width: 3em; 21 | height: 2em; 22 | padding: 0; 23 | margin: 0 0.5em 0 0; 24 | border-radius: 1024px; 25 | justify-content: center; 26 | box-shadow: none; 27 | align-items: center; 28 | border: 1px solid #CCC; 29 | } 30 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/input/ChatInput.js: -------------------------------------------------------------------------------- 1 | let ChatInput = function(parent) { 2 | this.parent = parent; 3 | 4 | this.tag = document.createElement("div"); 5 | this.tag.className = "ChatInput"; 6 | 7 | this.input = document.createElement("input"); 8 | this.input.type = "text"; 9 | this.input.onkeypress = this.onkeypress.bind(this); 10 | this.tag.append(this.input); 11 | 12 | this.button = document.createElement('div'); 13 | this.tag.append(this.button); 14 | this.button.className = 'Button SendButton'; 15 | this.button.textContent = '\u25BA'; 16 | this.button.onclick = this.userInputReady.bind(this); 17 | }; 18 | 19 | ChatInput.prototype.enable = function(enabled) { 20 | this.input.disabled = !enabled; 21 | }; 22 | 23 | ChatInput.prototype.set = function(text) { 24 | this.input.value = text; 25 | }; 26 | 27 | ChatInput.prototype.onkeypress = async function(e) { 28 | switch(e.keyCode) { 29 | case 13: { 30 | this.userInputReady(); 31 | } break; 32 | } 33 | }; 34 | 35 | ChatInput.prototype.userInputReady = async function(e) { 36 | let text = this.input.value.trim(); 37 | if (0 < text.length) { 38 | await this.parent.userInputReady(text); 39 | } 40 | }; 41 | 42 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/messagebox/MessageBox.css: -------------------------------------------------------------------------------- 1 | div.MessageBox { 2 | position: relative; 3 | display: flex; 4 | flex-direction: column-reverse; 5 | overflow-y: auto; 6 | width: calc(100% - 1em); 7 | margin: 0.5em; 8 | box-shadow: 0 0 4px #868686; 9 | border-radius: 3px; 10 | font-family: monospace; 11 | background-color: rgb(240, 240, 240); 12 | } 13 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/messagebox/MessageBox.js: -------------------------------------------------------------------------------- 1 | let MessageBox = function(parent) { 2 | this.parent = parent; 3 | 4 | this.tag = document.createElement("div"); 5 | this.tag.className = "MessageBox"; 6 | 7 | this.rows = []; 8 | this.line = 0; 9 | }; 10 | 11 | MessageBox.prototype.add = function(message) { 12 | let showName = true; 13 | if (0 < this.rows.length) { 14 | let lastRow = this.rows[this.rows.length - 1]; 15 | showName = (lastRow.message.from != message.from); 16 | } 17 | 18 | let messageRow = new MessageRow(this); 19 | messageRow.set(message, showName, message.own); 20 | messageRow.tag.style["order"] = -(this.line++); 21 | 22 | this.tag.append(messageRow.tag); 23 | this.rows.push(messageRow); 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/messagebox/messagerow/MessageRow.css: -------------------------------------------------------------------------------- 1 | div.MessageRow { 2 | position: relative; 3 | display: flex; 4 | width: 100%; 5 | } 6 | 7 | 8 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/messagebox/messagerow/MessageRow.js: -------------------------------------------------------------------------------- 1 | let MessageRow = function(parent) { 2 | this.parent = parent; 3 | 4 | this.tag = document.createElement("div"); 5 | this.tag.className = "MessageRow"; 6 | 7 | this.bubble = new Bubble(this); 8 | this.tag.append(this.bubble.tag); 9 | 10 | this.message = null; 11 | }; 12 | 13 | MessageRow.prototype.set = function(message, showName, own) { 14 | this.message = message; 15 | this.bubble.set(message, showName, own); 16 | 17 | this.tag.style['flex-direction'] = own ? 'row-reverse' : 'row'; 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/messagebox/messagerow/bubble/Bubble.css: -------------------------------------------------------------------------------- 1 | div.Bubble { 2 | position: relative; 3 | display: flex; 4 | flex-wrap: wrap; 5 | flex-direction: column; 6 | margin: 0.35em 0.25em 0.25em; 7 | padding: 0.35em 0.7em; 8 | border-radius: 5px; 9 | width: fit-content; 10 | background-color: rgb(255, 255, 250); 11 | color: #222; 12 | 13 | border-top: 1px solid #EEE; 14 | border-right: 1px solid #EEE; 15 | border-bottom: 1px solid #CCC; 16 | border-left: 1px solid #CCC; 17 | } 18 | 19 | div.NamedBubble { 20 | margin-top: 0; 21 | } 22 | 23 | div.OwnBubble { 24 | background-color: #e6ffd2; 25 | } 26 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/messagebox/messagerow/bubble/Bubble.js: -------------------------------------------------------------------------------- 1 | let Bubble = function(parent) { 2 | this.parent = parent; 3 | 4 | this.tag = document.createElement("div"); 5 | this.tag.className = "Bubble"; 6 | 7 | this.name = new Name(this); 8 | this.tag.append(this.name.tag); 9 | 10 | this.message = new Message(this); 11 | this.tag.append(this.message.tag); 12 | }; 13 | 14 | Bubble.prototype.set = function(message, showName, own) { 15 | let method = showName ? this.tag.classList.remove : this.tag.classList.add; 16 | method.call(this.tag.classList, "NamedBubble"); 17 | this.tag.classList[(showName && !own) ? 'add' : 'remove']('NamedBubble'); 18 | this.tag.classList[own ? 'add' : 'remove']('OwnBubble'); 19 | 20 | //let name = message.from.substring(message.from.length - 10, message.from.length); 21 | this.name.set(message, showName && !own); 22 | 23 | this.message.set(message.text); 24 | }; 25 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/messagebox/messagerow/bubble/message/Message.css: -------------------------------------------------------------------------------- 1 | div.Message { 2 | padding: 0.25em 0; 3 | } 4 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/messagebox/messagerow/bubble/message/Message.js: -------------------------------------------------------------------------------- 1 | let Message = function(parent) { 2 | this.parent = parent; 3 | 4 | this.tag = document.createElement("div"); 5 | this.tag.className = "Message"; 6 | }; 7 | 8 | Message.prototype.set = function(text) { 9 | this.tag.textContent = text; 10 | }; 11 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/messagebox/messagerow/bubble/name/Name.css: -------------------------------------------------------------------------------- 1 | div.Bubble div.Name { 2 | display: flex; 3 | font-weight: bold; 4 | margin: 0.25em 0; 5 | font-size: 80%; 6 | align-items: baseline; 7 | } 8 | 9 | div.Bubble div.Name div.Label { 10 | margin-left: 1em; 11 | } 12 | 13 | div.Bubble div.Name div.InputRow { 14 | width: initial; 15 | margin: 0; 16 | } 17 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[chat]/chatbox/messagebox/messagerow/bubble/name/Name.js: -------------------------------------------------------------------------------- 1 | let Name = function(parent) { 2 | this.parent = parent; 3 | 4 | this.tag = document.createElement("div"); 5 | this.tag.className = "Name"; 6 | 7 | this.signal = new Signal(this, ''); 8 | this.tag.append(this.signal.tag); 9 | 10 | this.label = document.createElement('div'); 11 | this.tag.append(this.label); 12 | this.label.className = 'Label'; 13 | }; 14 | 15 | Name.prototype.set = function(message, show) { 16 | if (show) { 17 | this.paintName(message.from); 18 | } 19 | 20 | this.tag.style.display = show ? "" : "none"; 21 | this.label.textContent = message.from; 22 | 23 | if (message.rssi) { 24 | this.signal.input.setDb(message.rssi); 25 | } 26 | }; 27 | 28 | Name.prototype.paintName = function(name) { 29 | let rng = new Math.seedrandom(name); 30 | let r = Math.floor(256 * rng()); 31 | let g = Math.floor(256 * rng()); 32 | let b = Math.floor(256 * rng()); 33 | this.label.style["color"] = `rgb(${r},${g},${b})`; 34 | }; 35 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[console]/Console.css: -------------------------------------------------------------------------------- 1 | div.Console { 2 | display: flex; 3 | flex-direction: column-reverse; 4 | width: calc(100% - 1em); 5 | margin: 0 0.5em; 6 | height: 10em; 7 | background-color: white; 8 | box-shadow: 0 0 5px #888; 9 | text-align: left; 10 | font-family: monospace; 11 | font-size: 85%; 12 | overflow-y: auto; 13 | } 14 | 15 | div.Console div.Line { 16 | width: 99%; 17 | margin: 0.5%; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[console]/Console.js: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////// 2 | // Console 3 | let Console = function(parent) { 4 | this.parent = parent; 5 | 6 | this.tag = document.createElement('div'); 7 | this.tag.className = 'Console'; 8 | 9 | this.length = 0; 10 | this.lines = 0; 11 | this.elements = []; 12 | }; 13 | 14 | Console.MAX_LINES = 40; 15 | 16 | Console.prototype.init = function(data) { 17 | 18 | }; 19 | 20 | Console.prototype.addTextLine = function(text) { 21 | let lineElement = null; 22 | 23 | if (Console.MAX_LINES > this.length) { 24 | this.length += 1; 25 | lineElement = document.createElement('div'); 26 | lineElement.className = 'Line'; 27 | this.tag.append(lineElement); 28 | this.elements.push(lineElement); 29 | } else { 30 | let index = (this.lines % this.length); 31 | lineElement = this.elements[index]; 32 | } 33 | 34 | lineElement.textContent = text; 35 | lineElement.style['order'] = -(this.lines++); 36 | }; 37 | 38 | Console.prototype.pong = function(pong) { 39 | 40 | }; 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[crypto]/AESM.js: -------------------------------------------------------------------------------- 1 | // /////////////////////////////////////////////////////////////////////////////// 2 | // AESM 3 | // https://github.com/ricmoo/aes-js 4 | // 5 | // Browser crypto can be scary. Do you have an evil extension 6 | // installed? We can't tell. Further, have we been tortured 7 | // into serving you custom, targeted JavaScript? Hopefully 8 | // you're not that important. 9 | // So: only use this page if (1) you feel your browser is 10 | // clean and (2) a life doesn't depend on it. 11 | 12 | let AESM = function(key) { 13 | this.encoder = new TextEncoder('UTF-8'); 14 | this.decoder = new TextDecoder('UTF-8'); 15 | 16 | let keyBuffer = key.b16ToAB();//this.encoder.encode(key); 17 | this.key = new Uint8Array(keyBuffer); 18 | }; 19 | 20 | AESM.prototype.encrypt = function(buffer) { 21 | var iv = new Uint8Array(16); 22 | window.crypto.getRandomValues(iv); 23 | let bytes = aesjs.padding.pkcs7.pad(buffer); 24 | var aesCbc = new aesjs.ModeOfOperation.cbc(this.key, iv); 25 | var encryptedBytes = aesCbc.encrypt(bytes); 26 | var ebuffer = new Uint8Array(iv.length + encryptedBytes.length); 27 | ebuffer.set(iv); 28 | ebuffer.set(encryptedBytes, iv.length); 29 | return ebuffer; 30 | }; 31 | 32 | AESM.prototype.decrypt = function(ebuffer) { 33 | var iv = new Uint8Array(ebuffer.buffer, 0, 16); 34 | let edata = new Uint8Array(ebuffer.buffer, 16); 35 | var aesCbc = new aesjs.ModeOfOperation.cbc(this.key, iv); 36 | let decryptedBytes = aesCbc.decrypt(edata); 37 | let buffer = aesjs.padding.pkcs7.strip(decryptedBytes); 38 | return buffer; 39 | }; 40 | 41 | /* 42 | AESM.prototype.encrypt = function(text) { 43 | var iv = new Uint8Array(16); 44 | window.crypto.getRandomValues(iv); 45 | let textBytes = aesjs.padding.pkcs7.pad(this.encoder.encode(text)); 46 | var aesCbc = new aesjs.ModeOfOperation.cbc(this.key, iv); 47 | var encryptedBytes = aesCbc.encrypt(textBytes); 48 | var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes); 49 | var c = new Int8Array(iv.length + encryptedBytes.length); 50 | c.set(iv); 51 | c.set(encryptedBytes, iv.length); 52 | let edata = c.buffer.toB64(); 53 | return edata; 54 | }; 55 | 56 | AESM.prototype.decrypt = function(encrypted64) { 57 | let buffer = encrypted64.b64ToAB(); 58 | var iv = new Uint8Array(buffer, 0, 16); 59 | let edata = new Uint8Array(buffer, 16); 60 | var aesCbc = new aesjs.ModeOfOperation.cbc(this.key, iv); 61 | let decryptedBytes = aesCbc.decrypt(edata); 62 | let paddedData = aesjs.padding.pkcs7.strip(decryptedBytes); 63 | let data = this.decoder.decode(paddedData); 64 | return data; 65 | }; 66 | */ 67 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[inputs]/pins.js: -------------------------------------------------------------------------------- 1 | // TODO:: move it 2 | let PINS = {}; 3 | PINS = []; 4 | PINS.push(['unused', -1]); 5 | PINS.push(['GPIO0 - D3', 0]); 6 | PINS.push(['GPIO1', 1]); 7 | PINS.push(['GPIO2 - D4', 2]); 8 | PINS.push(['GPIO3', 3]); 9 | PINS.push(['GPIO4 - D2', 4]); 10 | PINS.push(['GPIO5 - D1', 5]); 11 | PINS.push(['GPIO6', 6]); 12 | PINS.push(['GPIO7', 7]); 13 | PINS.push(['GPIO8', 8]); 14 | PINS.push(['GPIO9', 9]); 15 | PINS.push(['GPIO10', 10]); 16 | PINS.push(['GPIO11', 11]); 17 | PINS.push(['GPIO12 - D6', 12]); 18 | PINS.push(['GPIO13 - D7', 13]); 19 | PINS.push(['GPIO14 - D5', 14]); 20 | PINS.push(['GPIO15 - D8', 15]); 21 | PINS.push(['GPIO16 - D0', 16]); 22 | 23 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[inputs]/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin:0; 3 | padding:0; 4 | color: #555; 5 | background-color: #EBEBDA; 6 | --short-box-shadow: 0 0 3px #111; 7 | --light-color: rgb(40, 142, 142); 8 | --dark-color: rgb(31, 94, 94); 9 | } 10 | 11 | div { 12 | position: relative; 13 | display: inline-block; 14 | } 15 | 16 | input { 17 | text-align: center; 18 | } 19 | 20 | h1 { 21 | font-size: 5vw; 22 | text-align: center; 23 | } 24 | 25 | div.header { 26 | width: 100%; 27 | background: linear-gradient(rgb(20, 90, 90), rgb(40, 142, 142)); 28 | box-shadow: 0 0 4px #222; 29 | } 30 | 31 | .logo_colour { 32 | color: #CC9514; 33 | } 34 | 35 | div.header, 36 | div.header div.logo, 37 | div.header div.logo div.title { 38 | display: flex; 39 | justify-content: center; 40 | align-items: center; 41 | } 42 | 43 | div.header div.logo div.title { 44 | color: #555; 45 | font-size: 1.5em; 46 | padding: 0.25em 0; 47 | font-family: monospace; 48 | color: white; 49 | font-style: italic; 50 | font-weight: bold; 51 | } 52 | 53 | @media(orientation:portrait) { 54 | div.header div.logo div.title { 55 | font-size: 1.25em; 56 | } 57 | } 58 | 59 | @media(orientation:landscape) { 60 | div.header div.logo div.title { 61 | font-size: 1.5em; 62 | } 63 | } 64 | 65 | 66 | div.PageContent { 67 | width: calc(100% - 2px - 1em); 68 | margin: 0.5em; 69 | text-align: center; 70 | background-color: #BBB; 71 | border: 1px solid #CCC; 72 | } 73 | 74 | div.PageContent div.ContentMarc { 75 | padding: 0; 76 | color: #555; 77 | width: 100%; 78 | font-family: Arial, Helvetica, Sans-serif; 79 | background: linear-gradient(#c9c9c9, #eee, #c9c9c9); 80 | box-shadow: 0 0 5px #777; 81 | } 82 | 83 | @media(orientation:portrait) { 84 | div.PageContent { 85 | width: calc(100% - 2px); 86 | margin: 0.5em 0; 87 | } 88 | } 89 | 90 | 91 | 92 | div.ContentFooter { 93 | width: 100%; 94 | display: flex; 95 | flex-wrap: wrap; 96 | justify-content: center; 97 | } 98 | 99 | div.ContentFooter div.TextContent { 100 | width: 100%; 101 | } 102 | 103 | div.ContentFooter div.CopyR { 104 | width: 100%; 105 | font-size: 80%; 106 | margin: 1em 0; 107 | } 108 | 109 | div.ContentFooter div.FooterLogo { 110 | width: 80%; 111 | max-width: 25em; 112 | } 113 | 114 | div.ContentWraper { 115 | width: 100%; 116 | margin: 0; 117 | max-width: 130vh; 118 | } 119 | 120 | div.Configuration div.Selected { 121 | background-color: transparent; 122 | font-weight: bold; 123 | border-top: 1px solid #EEE; 124 | border-right: 1px solid #CCC; 125 | border-left: 1px solid #EEE; 126 | border-bottom: 1px solid transparent; 127 | box-shadow: 0 0 4px #7d7d7d; 128 | } 129 | 130 | div.Configuration div.Title { 131 | width: 100%; 132 | text-align: left; 133 | margin: 3% 0 0.5%; 134 | font-weight: bold; 135 | text-indent: 0.5em; 136 | } 137 | 138 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[iserial]/ISerial.js: -------------------------------------------------------------------------------- 1 | let ISerial = function() { 2 | this.ondata = (data) => {}; 3 | this.onconnect = () => {}; 4 | this.ondisconnect = () => {}; 5 | this.onerror = (e) => {}; 6 | this.onlog = (text) => {}; 7 | }; 8 | 9 | ISerial.prototype.open = function(options) { 10 | 11 | }; 12 | 13 | ISerial.prototype.close = function() { 14 | 15 | }; 16 | 17 | ISerial.prototype.send = function(data) { 18 | 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[iserial]/WebAndroidSerial.js: -------------------------------------------------------------------------------- 1 | let WebAndroidSerial = function(parent) { 2 | ISerial.call(this); 3 | WebAndroidSerial.instance = this; 4 | }; for (let i in ISerial.prototype) WebAndroidSerial.prototype[i] = ISerial.prototype[i]; 5 | 6 | WebAndroidSerial.prototype.open = async function(options) { 7 | try { 8 | this.onlog(`connecting: ${options.baudrate}`); 9 | let optionsSTR = JSON.stringify(options); 10 | AndroidSerial.connect(optionsSTR); 11 | } catch(e) { 12 | this.onlog(e); 13 | this.onerror(e); 14 | } 15 | }; 16 | 17 | WebAndroidSerial.prototype.onAndroidOpen = async function(options) { 18 | try { 19 | this.onlog("connected"); 20 | this.onconnect(); 21 | } catch(e) { 22 | this.onlog("open USB error"); 23 | this.onlog(e); 24 | this.onerror(e); 25 | } 26 | }; 27 | 28 | WebAndroidSerial.prototype.close = function() { 29 | AndroidSerial.close(); 30 | }; 31 | 32 | WebAndroidSerial.prototype.send = async function(bytes) { 33 | AndroidSerial.send(bytes); 34 | }; 35 | 36 | WebAndroidSerial.prototype.onAndroidData = function(b64) { 37 | try { 38 | let buffer = b64.b64ToAB(); 39 | let uint8Buffer = new Uint8Array(buffer); 40 | this.ondata(uint8Buffer); 41 | } catch(e) { 42 | this.onlog(e); 43 | } 44 | }; 45 | 46 | WebAndroidSerial.prototype.onAndroidClose = function(b64) { 47 | try { 48 | this.ondisconnect(); 49 | } catch(e) { 50 | this.onlog(e); 51 | } 52 | }; 53 | 54 | WebAndroidSerial.prototype.onAndroidLog = async function(text) { 55 | this.onlog(text); 56 | }; 57 | 58 | WebAndroidSerial.instance = null; 59 | function AndroidSerial_ondata(b64) { 60 | if (WebAndroidSerial.instance) { 61 | WebAndroidSerial.instance.onAndroidData(b64); 62 | } 63 | } 64 | 65 | function AndroidSerial_onopen() { 66 | if (WebAndroidSerial.instance) { 67 | WebAndroidSerial.instance.onAndroidOpen(); 68 | } 69 | } 70 | 71 | function AndroidSerial_onclose() { 72 | if (WebAndroidSerial.instance) { 73 | WebAndroidSerial.instance.onAndroidClose(); 74 | } 75 | } 76 | 77 | function AndroidSerial_log(text) { 78 | if (WebAndroidSerial.instance) { 79 | WebAndroidSerial.instance.onAndroidLog(text); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[iserial]/WebSerial.js: -------------------------------------------------------------------------------- 1 | let WebSerial = function() { 2 | ISerial.call(this); 3 | }; for (let i in ISerial.prototype) WebSerial.prototype[i] = ISerial.prototype[i]; 4 | 5 | WebSerial.filters = []; 6 | WebSerial.filters.push({ 'usbVendorId' : 0x0403 }); 7 | WebSerial.filters.push({ 'usbVendorId' : 0x1A86 }); 8 | WebSerial.filters.push({ 'usbVendorId' : 0x1B4F }); 9 | 10 | WebSerial.prototype.open = async function(options) { 11 | try { 12 | this.onlog(`connecting: ${options.baudrate}`); 13 | this.port = await navigator.serial.requestPort({ 'filters' : WebSerial.filters }); 14 | await this.port.open({'baudRate':options.baudrate}); 15 | } catch(e) { 16 | console.log(e); 17 | } 18 | 19 | try { 20 | this.writer = this.port.writable.getWriter(); 21 | this.reader = this.port.readable.getReader(); 22 | this.onconnect(); 23 | this.onlog("connected"); 24 | await this.read(); 25 | } catch(e) { 26 | this.onerror(e); 27 | } 28 | }; 29 | 30 | WebSerial.prototype.close = function() { 31 | try { 32 | this.port.close(); 33 | this.writer.releaseLock(); 34 | //this.reader.releaseLock(); 35 | } catch(e) { 36 | this.onlog(e); 37 | } 38 | this.port = null; 39 | }; 40 | 41 | WebSerial.prototype.send = async function(bytes) { 42 | await this.writer.write(bytes); 43 | }; 44 | 45 | WebSerial.prototype.read = async function() { 46 | const { value, done } = await this.reader.read(); 47 | if (done) { 48 | console.log("Done releasing reader"); 49 | this.ondisconnect(); 50 | this.reader.releaseLock(); 51 | } else { 52 | this.ondata(value); 53 | setTimeout(async () => { try { await this.read(); } catch(e) { this.ondisconnect(); this.onlog(e); }}, 0); 54 | } 55 | }; 56 | 57 | 58 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[serialport]/SerialPort.css: -------------------------------------------------------------------------------- 1 | div.SerialPort { 2 | width: 100%; 3 | } 4 | 5 | div.SerialPort div.Title { 6 | width: 100%; 7 | text-align: left; 8 | margin: 3% 0 .5%; 9 | font-weight: bold; 10 | text-indent: .5em; 11 | } 12 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[serialport]/SerialPort.js: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////// 2 | // SerialPort 3 | let SerialPort = function(parent, name) { 4 | Node.call(this, parent, name); 5 | 6 | this.tag = document.createElement('div'); 7 | this.tag.className = 'SerialPort'; 8 | this.tag.node = this; 9 | 10 | this.title = document.createElement('div'); 11 | this.title.className = 'Title'; 12 | this.title.textContent = 'SerialPort port'; 13 | this.tag.append(this.title); 14 | this.title.style.width = 'calc(100% - 1.2em)'; 15 | 16 | this.separator = document.createElement('div'); 17 | this.separator.className = 'Separator'; 18 | this.tag.append(this.separator); 19 | 20 | this.status = new StatusRow(this, 'status'); 21 | this.tag.append(this.status.tag); 22 | this.status.input.label.textContent = 'unknown'; 23 | this.status.input.point.style['background-color'] = '#FF0'; 24 | 25 | this.baudrate = new InputRow(this, 'Baudrate', 'select', ''); 26 | this.baudrate.addOptions(SerialPort.SPEEDS); 27 | this.tag.append(this.baudrate.tag); 28 | //this.baudrate.setHelp('This is the default power the module should emmit with.'); 29 | 30 | this.config = new InputRow(this, 'Configuration', 'select', ''); 31 | this.config.addOptions(SerialPort.CONFIG); 32 | this.tag.append(this.config.tag); 33 | //this.config.setHelp('This is the default power the module should emmit with.'); 34 | 35 | this.advanced = new Advanced(this, 'Advanced'); 36 | this.advanced.tag.className = 'Advanced'; 37 | this.tag.append(this.advanced.tag); 38 | 39 | this.invert = new InputRow(this, 'invert', 'checkbox', ''); 40 | this.invert.input.input.className = ''; 41 | this.advanced.append(this.invert.tag); 42 | 43 | this.bsize = new InputRow(this, 'rx buffer', 'number', ''); 44 | this.bsize.validator = new IntegerValidator(this.bsize, 1); 45 | this.advanced.append(this.bsize.tag); 46 | this.bsize.tag.style['display'] = 'none'; 47 | 48 | this.rx = new InputRow(this, 'RX', 'select', ''); 49 | this.rx.addOptions(PINS); 50 | this.rx.addOptions([['RXD0', 127]]); 51 | this.advanced.append(this.rx.tag); 52 | 53 | this.tx = new InputRow(this, 'TX', 'select', ''); 54 | this.tx.addOptions(PINS); 55 | this.tx.addOptions([['TXD0', 127]]); 56 | this.advanced.append(this.tx.tag); 57 | }; 58 | 59 | // Inheritance 60 | for (let i in Node.prototype) 61 | SerialPort.prototype[i] = Node.prototype[i]; 62 | 63 | 64 | SerialPort.TYPES = []; 65 | SerialPort.TYPES.push(['Software', SerialPort.TYPES.length]); 66 | SerialPort.TYPES.push(['Hardware', SerialPort.TYPES.length]); 67 | 68 | SerialPort.SPEEDS = []; 69 | SerialPort.SPEEDS.push(['300', 300]); 70 | SerialPort.SPEEDS.push(['600', 600]); 71 | SerialPort.SPEEDS.push(['1200', 1200]); 72 | SerialPort.SPEEDS.push(['2400', 2400]); 73 | SerialPort.SPEEDS.push(['4800', 4800]); 74 | SerialPort.SPEEDS.push(['9600', 9600]); 75 | SerialPort.SPEEDS.push(['14400', 14400]); 76 | SerialPort.SPEEDS.push(['19200', 19200]); 77 | SerialPort.SPEEDS.push(['28800', 28800]); 78 | SerialPort.SPEEDS.push(['38400', 38400]); 79 | SerialPort.SPEEDS.push(['57600', 57600]); 80 | SerialPort.SPEEDS.push(['115200', 115200]); 81 | 82 | SerialPort.CONFIG = []; 83 | SerialPort.CONFIG.push(['SERIAL_5N1', SerialPort.CONFIG.length]); 84 | SerialPort.CONFIG.push(['SERIAL_6N1', SerialPort.CONFIG.length]); 85 | SerialPort.CONFIG.push(['SERIAL_7N1', SerialPort.CONFIG.length]); 86 | SerialPort.CONFIG.push(['SERIAL_8N1', SerialPort.CONFIG.length]); 87 | SerialPort.CONFIG.push(['SERIAL_5N2', SerialPort.CONFIG.length]); 88 | SerialPort.CONFIG.push(['SERIAL_6N2', SerialPort.CONFIG.length]); 89 | SerialPort.CONFIG.push(['SERIAL_7N2', SerialPort.CONFIG.length]); 90 | SerialPort.CONFIG.push(['SERIAL_8N2', SerialPort.CONFIG.length]); 91 | SerialPort.CONFIG.push(['SERIAL_5E1', SerialPort.CONFIG.length]); 92 | SerialPort.CONFIG.push(['SERIAL_6E1', SerialPort.CONFIG.length]); 93 | SerialPort.CONFIG.push(['SERIAL_7E1', SerialPort.CONFIG.length]); 94 | SerialPort.CONFIG.push(['SERIAL_8E1', SerialPort.CONFIG.length]); 95 | SerialPort.CONFIG.push(['SERIAL_5E2', SerialPort.CONFIG.length]); 96 | SerialPort.CONFIG.push(['SERIAL_6E2', SerialPort.CONFIG.length]); 97 | SerialPort.CONFIG.push(['SERIAL_7E2', SerialPort.CONFIG.length]); 98 | SerialPort.CONFIG.push(['SERIAL_8E2', SerialPort.CONFIG.length]); 99 | SerialPort.CONFIG.push(['SERIAL_5O1', SerialPort.CONFIG.length]); 100 | SerialPort.CONFIG.push(['SERIAL_6O1', SerialPort.CONFIG.length]); 101 | SerialPort.CONFIG.push(['SERIAL_7O1', SerialPort.CONFIG.length]); 102 | SerialPort.CONFIG.push(['SERIAL_8O1', SerialPort.CONFIG.length]); 103 | SerialPort.CONFIG.push(['SERIAL_5O2', SerialPort.CONFIG.length]); 104 | SerialPort.CONFIG.push(['SERIAL_6O2', SerialPort.CONFIG.length]); 105 | SerialPort.CONFIG.push(['SERIAL_7O2', SerialPort.CONFIG.length]); 106 | SerialPort.CONFIG.push(['SERIAL_8O2', SerialPort.CONFIG.length]); 107 | 108 | SerialPort.MODES = []; 109 | SerialPort.MODES.push(['SERIAL_FULL', SerialPort.MODES.length]); 110 | SerialPort.MODES.push(['SERIAL_RX_ONLY', SerialPort.MODES.length]); 111 | SerialPort.MODES.push(['SERIAL_TX_ONLY', SerialPort.MODES.length]); 112 | 113 | SerialPort.prototype.init = function() { 114 | 115 | }; 116 | 117 | SerialPort.prototype.state = function(params) { 118 | this.loaded = true; 119 | 120 | let statusElement = params.get('status'); 121 | if (statusElement) { 122 | let status = statusElement.int(); 123 | this.status.input.label.textContent = status ? 'initialized' : 'stoped'; 124 | this.status.input.point.style['background-color'] = status ? '#0F0' : '#F00'; 125 | } 126 | 127 | let config = params.get("config"); 128 | if (config) { 129 | let baudrateElement = config.get('baudrate'); 130 | if (baudrateElement) { 131 | let baudrate = baudrateElement.int(); 132 | this.baudrate.pong(baudrate); 133 | } 134 | 135 | let configElement = config.get('config'); 136 | if (configElement) { 137 | let config = configElement.int(); 138 | this.config.pong(config); 139 | } 140 | 141 | let invertElement = config.get('invert'); 142 | if (invertElement) { 143 | let invert = invertElement.int(); 144 | this.invert.pong(invert); 145 | } 146 | 147 | let bsizeElement = config.get('bsize'); 148 | if (bsizeElement) { 149 | this.bsize.tag.style['display'] = ''; 150 | let bsize = bsizeElement.uint(); 151 | this.bsize.pong(bsize); 152 | } 153 | 154 | let rxElement = config.get('rx'); 155 | if (rxElement) { 156 | let rx = rxElement.int(); 157 | this.rx.pong(rx); 158 | } 159 | 160 | let txElement = config.get('tx'); 161 | if (txElement) { 162 | let tx = txElement.int(); 163 | this.tx.pong(tx); 164 | } 165 | } 166 | }; 167 | 168 | SerialPort.prototype.showMessage = function(message) { 169 | this.parent.showMessage(message, true); 170 | }; 171 | 172 | SerialPort.prototype.isChanged = function(command) { 173 | return this.baudrate.changed 174 | || this.config.changed 175 | || this.invert.changed 176 | || this.bsize.changed 177 | || this.rx.changed 178 | || this.tx.changed; 179 | }; 180 | 181 | SerialPort.prototype.save = function(command) { 182 | Node.prototype.save.call(this, command); 183 | let isChanged = this.isChanged(); 184 | if (isChanged) { 185 | let serial = command.newObject('save'); 186 | 187 | if (this.baudrate.changed) { 188 | let baudrate = serial.newNumber('baudrate'); 189 | baudrate.setUInt32(this.baudrate.value()|0); 190 | } 191 | 192 | if (this.config.changed) { 193 | let config = serial.newNumber('config'); 194 | config.setUInt8(this.config.value()|0); 195 | } 196 | 197 | if (this.invert.changed) { 198 | let invert = serial.newNumber('invert'); 199 | invert.setUInt8(this.invert.value()|0); 200 | } 201 | 202 | if (this.bsize.changed) { 203 | let bsize = serial.newNumber('bsize'); 204 | bsize.setUInt16(this.bsize.value()|0); 205 | } 206 | 207 | if (this.rx.changed) { 208 | let rx = serial.newNumber('rx'); 209 | rx.setUInt8(this.rx.value()|0); 210 | } 211 | 212 | if (this.tx.changed) { 213 | let tx = serial.newNumber('tx'); 214 | tx.setUInt8(this.tx.value()|0); 215 | } 216 | } 217 | }; 218 | 219 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/[std]/std.js: -------------------------------------------------------------------------------- 1 | ArrayBuffer.prototype.toB64 = function(url = false) { 2 | let base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' + (url ? '-_' : '+/'); 3 | let str = '', ui8 = new Uint8Array(this); 4 | for (let i = 0, b = 0; i < ui8.length; i++) { 5 | let ui = ui8[i], le = 2 * (i % 3), p = 2 + le, na = (ui >> p); 6 | str += base64Chars[na | b]; 7 | let p2 = 2**p - 1, ml = (4 - le); 8 | b = (ui & p2) << ml; 9 | if (0 == ml || i == (ui8.length - 1)) { 10 | str += base64Chars[b]; 11 | b = 0; 12 | } 13 | } 14 | while (!url && (str.length & 3) > 0) str += '='; 15 | return str; 16 | }; 17 | 18 | ArrayBuffer.prototype.toB16 = function() { 19 | let str = ''; 20 | let uia = new Uint8Array(this); 21 | for (let ui of uia) { 22 | let b16 = ui.toString(16); 23 | str += b16.padStart(2, '0'); 24 | } 25 | return str; 26 | }; 27 | 28 | String.prototype.b64ToAB = function(url = false) { 29 | let base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' + (url ? '-_' : '+/'); 30 | let str = this.replace(/=/gi, ''); 31 | let length = Math.floor(str.length * 6 / 8); 32 | let arrayBuffer = new ArrayBuffer(length); 33 | let uia = new Uint8Array(arrayBuffer); 34 | for (let i = 0, si = -1; i < length; i++) { 35 | let m = 2 * (i % 3), e1 = 6 - m, b1 = 2**e1 - 1; 36 | si += +(0 == i % 3); 37 | let c = str[si], ci1 = base64Chars.indexOf(c); 38 | uia[i] = (ci1 & b1) << (2 + m); 39 | let e2 = 4 - m, b2 = 63 - (2**e2 - 1), c2 = str[++si] || 'A', ci2 = base64Chars.indexOf(c2); 40 | uia[i] |= (ci2 & b2) >> (4 - m); 41 | } 42 | return arrayBuffer; 43 | }; 44 | 45 | String.prototype.b16ToAB = function() { 46 | let str = (0 == (this.length % 2)) ? this : ('0' + this); 47 | let arrayBuffer = new ArrayBuffer(str.length / 2); 48 | let uia = new Uint8Array(arrayBuffer); 49 | for (let j = 0; j < uia.length; j++) { 50 | let s = str.substring(2 * j, 2 * j + 2); 51 | uia[j] = parseInt(s, 16); 52 | } 53 | return arrayBuffer; 54 | }; 55 | 56 | String.prototype.JWK = async function() { 57 | let promise = new Promise((resolve, reject) => { 58 | let worker = new Worker('lib/crypto/JwkGenerator.js?v=1'); 59 | worker.onmessage = function(e) { 60 | resolve(e.data); 61 | this.terminate(); 62 | }; 63 | worker.postMessage(this); 64 | }); 65 | return promise; 66 | }; 67 | 68 | 69 | Number.prototype.battery = function() { 70 | let bin3v3 = 1024; 71 | let binMax = 3.9 * bin3v3 / 3.3; 72 | let binMin = 3.5 * bin3v3 / 3.3; 73 | let range = binMax - binMin; 74 | let read = 2 * this - binMin; 75 | let percentage = Math.max(0, Math.min(100 * (read / range), 100)); 76 | return percentage; 77 | }; 78 | 79 | Number.prototype.mod = function(n) { 80 | return ((this % n) + n) % n; 81 | }; 82 | 83 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/assets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Configuration 55 | 56 | 57 | 58 | 59 |
60 | 63 |
64 |
65 |
66 |
67 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6200EE 4 | #3700B3 5 | #03DAC5 6 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FBFAFF 4 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | USBRFMApp 3 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/main/res/xml/device_filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/app/src/test/java/com/pulsartronic/usbrfmapp/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.pulsartronic.usbrfmapp; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath "com.android.tools.build:gradle:4.0.1" 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | maven { url "https://jitpack.io" } 20 | } 21 | } 22 | 23 | task clean(type: Delete) { 24 | delete rootProject.buildDir 25 | } -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMApp/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Oct 18 12:04:21 CEST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip 7 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /AndroidStudio/USBRFMApp/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name = "USBRFMApp" -------------------------------------------------------------------------------- /AndroidStudio/USBRFMAppKeystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/AndroidStudio/USBRFMAppKeystore.jks -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/USBRFMApp/App.cpp: -------------------------------------------------------------------------------- 1 | #include "USBRFMApp.h" 2 | 3 | void App_send(Node* cdNode, CDS::DataBuffer* params, CDS::DataBuffer* response) { 4 | USBRFMApp::App* app = (USBRFMApp::App*) cdNode; 5 | app->send(params, response); 6 | } 7 | 8 | USBRFMApp::App::App(Node* parent, const char* name) : Node(parent, name) { 9 | Method* send = new Node::Method(this, App_send); 10 | this->methods->set((char*) String(F("send")).c_str(), send); 11 | } 12 | 13 | USBRFMApp::App::~App() { 14 | 15 | } 16 | 17 | void USBRFMApp::App::setup() { 18 | 19 | } 20 | 21 | void USBRFMApp::App::loop() { 22 | 23 | } 24 | 25 | void USBRFMApp::App::state(CDS::DataBuffer* params, CDS::DataBuffer* response) { 26 | CDS::DataBuffer* object = this->rootIT(response); 27 | CDS::DataBuffer* state = CDS::Object::newObject(object, K("state")); 28 | } 29 | 30 | void USBRFMApp::App::onData(DataChannel* dataChannel, CDS::DataBuffer* data) { 31 | bool isNumber = CDS::Element::isNumber(data); 32 | if (isNumber) { 33 | CDS::DataBuffer* command = CDS::Element::newObject(); 34 | CDS::DataBuffer* object = this->rootIT(command); 35 | CDS::DataBuffer* ondata = CDS::Object::newObject(object, K("ondata")); 36 | CDS::DataBuffer* rssi = CDS::Object::newNumber(ondata, K("rssi")); 37 | CDS::Number::set(rssi, LoRa.packetRssi()); // Received Signal Strength Indicator 38 | CDS::DataBuffer* snr = CDS::Object::newNumber(ondata, K("snr")); 39 | CDS::Number::set(snr, LoRa.packetSnr()); // Signal-to-noise ratio 40 | CDS::DataBuffer* pfe = CDS::Object::newNumber(ondata, K("pfe")); 41 | CDS::Number::set(pfe, LoRa.packetFrequencyError()); // Packet Frequency Error 42 | CDS::Object::set(ondata, K("data"), data); 43 | this->command(command); 44 | CDS::DataBuffer* last = CDS::Element::last(data); 45 | data->prev->next = last->next; // it is deleted later 46 | delete command; 47 | } 48 | } 49 | 50 | void USBRFMApp::App::send(CDS::DataBuffer* params, CDS::DataBuffer* response) { 51 | int sent = 0; 52 | CDS::DataBuffer* data = CDS::Object::get(params, K("data")); 53 | bool isNumber = CDS::Element::isNumber(data); 54 | if (isNumber) { 55 | for (int i = 0; i < this->channels->length; i++) { 56 | DataChannel* channel = this->channels->get(i); 57 | sent += channel->send(data); 58 | yield(); 59 | } 60 | CDS::DataBuffer* object = this->rootIT(response); 61 | CDS::DataBuffer* sentObject = CDS::Object::newObject(object, K("sent")); 62 | CDS::DataBuffer* total = CDS::Object::newNumber(sentObject, K("total")); 63 | CDS::Number::set(total, sent); 64 | // CDS::DataBuffer* heap = CDS::Object::newNumber(sentObject, K("heap")); 65 | // CDS::Number::set(heap, ESP.getFreeHeap()); 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/USBRFMApp/Defaults.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * See DEFAULTS[] as the following data structure: 5 | * 6 | * { 7 | * "serial" : { 8 | * "baudrate" : 9600, 9 | * "config" : 3, 10 | * "invert" : false, 11 | * "bsize" : 128, 12 | * "rx" : 127, 13 | * "tx" : 127 14 | * }, 15 | * "rfm" : { 16 | * "freq" : { 17 | * "curr" : 868300000, 18 | * "min" : 858000000, 19 | * "max" : 878000000 20 | * }, 21 | * "txpw" : 17, 22 | * "sfac" : 7, 23 | * "sbw" : 125000, 24 | * "crat" : 5, 25 | * "plength" : 8, 26 | * "sw" : 57, 27 | * "crc" : true, 28 | * "iiq" : false, 29 | * "pins" : { 30 | * "miso" : 14, 31 | * "mosi" : 16, 32 | * "sck" : 15, 33 | * "nss" : 5, 34 | * "rst" : 7, 35 | * "dio" : [8, -1, -1, -1, -1, -1] 36 | * } 37 | * } 38 | * } 39 | * 40 | * Every entry starts with: TYPE | HM, SIZE 41 | * 42 | * example: 43 | * CDS::BINARY | 1, 0x06, 's','e','r','i','a','l' 44 | * 45 | * TYPE = CDS::BINARY data type 46 | * HM = 1 how many bytes we need to represent its length 47 | * SIZE = 0x06 data length represented using HM bytes, if HM = 2 it could be for example SIZE = 0x12, 0x03 48 | * CONTENT = 's','e','r','i','a','l' 49 | * 50 | * In the case of CDS::OBJECT, LENGTH tells us how many key/value pairs the object has 51 | * In the case of CDS::ARRAY, LENGTH tells us how many elements the array has 52 | * In the case of CDS::BINARY, LENGTH tells us how many bytes it has 53 | * 54 | */ 55 | 56 | const uint8_t DEFAULTS[] PROGMEM = { 57 | CDS::OBJECT | 1, 0x03, 58 | CDS::BINARY | 1, 0x06, 's','e','r','i','a','l', // see libraries/SerialPort/SerialPort.cpp 59 | CDS::OBJECT | 1, 0x06, // 6 key/values 60 | CDS::BINARY | 1, 0x08, 'b','a','u','d','r','a','t','e', 61 | CDS::BINARY | 1, 0x04, 0x00, 0x00, 0x25, 0x80, // 0x00002580 = 9600 62 | CDS::BINARY | 1, 0x06, 'c','o','n','f','i','g', 63 | CDS::BINARY | 1, 0x01, 0x03, // SERIAL_8N1 64 | CDS::BINARY | 1, 0x06, 'i','n','v','e','r','t', 65 | CDS::BINARY | 1, 0x01, 0x00, // false 66 | CDS::BINARY | 1, 0x05, 'b','s','i','z','e', 67 | CDS::BINARY | 1, 0x01, 0x80, // 128 68 | CDS::BINARY | 1, 0x02, 'r','x', 69 | CDS::BINARY | 1, 0x01, 0x7F, // 127 70 | CDS::BINARY | 1, 0x02, 't','x', 71 | CDS::BINARY | 1, 0x01, 0x7F, // 127 72 | CDS::BINARY | 1, 0x03, 'r','f','m', // see libraries/RFM/RFM.cpp 73 | CDS::OBJECT | 1, 0x0A, // 10 key/values 74 | CDS::BINARY | 1, 0x04, 'f','r','e','q', 75 | CDS::BINARY | 1, 0x04, 0x33, 0xC1, 0x34, 0xE0, // 0x33C134E0 = 868300000 76 | CDS::BINARY | 1, 0x04, 't','x','p','w', // tx power 77 | CDS::BINARY | 1, 0x01, 0x11, // = 17 78 | CDS::BINARY | 1, 0x04, 's','f','a','c', // spreading factor 79 | CDS::BINARY | 1, 0x01, 0x07, // = 7 80 | CDS::BINARY | 1, 0x03, 's','b','w', // signal bandwidth 81 | CDS::BINARY | 1, 0x04, 0x00, 0x01, 0xE8, 0x48, // = 125000 82 | CDS::BINARY | 1, 0x04, 'c','r','a','t', // codingrate4 83 | CDS::BINARY | 1, 0x01, 0x05, // = 5 84 | CDS::BINARY | 1, 0x07, 'p','l','e','n','g','t','h', // preamble length 85 | CDS::BINARY | 1, 0x01, 0x08, // = 8 86 | CDS::BINARY | 1, 0x02, 's','w', // sync word 87 | CDS::BINARY | 1, 0x01, 0x39, // = 0x39 88 | CDS::BINARY | 1, 0x03, 'c','r','c', 89 | CDS::BINARY | 1, 0x01, 0x01, // true 90 | CDS::BINARY | 1, 0x03, 'i','i','q', 91 | CDS::BINARY | 1, 0x01, 0x00, // false 92 | CDS::BINARY | 1, 0x04, 'p','i','n','s', // RFM PINS 93 | CDS::OBJECT | 1, 0x06, // 6 key/values 94 | CDS::BINARY | 1, 0x04, 'm','i','s','o', 95 | CDS::BINARY | 1, 0x01, 0x0E, 96 | CDS::BINARY | 1, 0x04, 'm','o','s','i', 97 | CDS::BINARY | 1, 0x01, 0x10, 98 | CDS::BINARY | 1, 0x03, 's','c','k', 99 | CDS::BINARY | 1, 0x01, 0x0F, 100 | CDS::BINARY | 1, 0x03, 'n','s','s', 101 | CDS::BINARY | 1, 0x01, 0x05, // 0x10, // 102 | CDS::BINARY | 1, 0x03, 'r','s','t', 103 | CDS::BINARY | 1, 0x01, 0x07, // 0x0F, // 104 | CDS::BINARY | 1, 0x03, 'd','i','o', 105 | CDS::ARRAY | 1, 0x02, // 2 elements 106 | CDS::BINARY | 1, 0x01, 0x08, // 0x04, // 107 | CDS::BINARY | 1, 0x01, 0xFF, 108 | CDS::BINARY | 1, 0x03, 'a','p','p', 109 | CDS::OBJECT | 1, 0x00 110 | }; 111 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/USBRFMApp/USBRFMApp.cpp: -------------------------------------------------------------------------------- 1 | #include "USBRFMApp.h" 2 | 3 | USBRFMApp::USBRFMApp() : RootNode(NULL, S("root")), serial(this, S("serial")), rfm(this, S("rfm")), app(this, S("app")) { 4 | this->nodes->set(this->serial.name, &this->serial); 5 | this->nodes->set(this->rfm.name, &this->rfm); 6 | this->nodes->set(this->app.name, &this->app); 7 | this->app.addDataChannel(&this->rfm.channel); 8 | this->addDataChannel(&this->serial.channel); 9 | } 10 | 11 | USBRFMApp::~USBRFMApp() { 12 | delete this->storageIterator.buffer; 13 | } 14 | 15 | void USBRFMApp::setup() { 16 | RootNode::setup(); 17 | 18 | size_t eepromSize = sizeof(DEFAULTS); 19 | #ifdef ESP8266 20 | EEPROM.begin(eepromSize); 21 | #else 22 | EEPROM.begin(); 23 | #endif 24 | CDS::EEPROMBuffer* eepromBuffer = new CDS::EEPROMBuffer(0); 25 | this->storageIterator = CDS::Iterator(eepromBuffer, eepromSize); 26 | bool validDefaults = CDS::Element::valid(&storageIterator); 27 | if (!validDefaults) { 28 | for (size_t i = (size_t) 0; i < eepromSize; i++) { 29 | uint8_t value = pgm_read_byte(DEFAULTS + i); 30 | EEPROM.write(i, value); 31 | } 32 | #ifdef ESP8266 33 | EEPROM.commit(); 34 | #endif 35 | } 36 | // TODO:: check version or structure 37 | 38 | this->serial.setup(); 39 | this->rfm.setup(); 40 | this->app.setup(); 41 | } 42 | 43 | void USBRFMApp::loop() { 44 | RootNode::loop(); 45 | this->serial.loop(); 46 | this->rfm.loop(); 47 | this->app.loop(); 48 | } 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/USBRFMApp/USBRFMApp.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Defaults.h" 5 | 6 | #ifndef __USBRFMApp__ 7 | #define __USBRFMApp__ 8 | 9 | class USBRFMApp : public RootNode { 10 | public: 11 | 12 | class App : public Node, public DataChannel::Handler { 13 | public: 14 | App(Node* parent, const char* name); 15 | virtual ~App(); 16 | virtual void onData(DataChannel* dataChannel, CDS::DataBuffer* data); 17 | virtual void setup(); 18 | virtual void loop(); 19 | virtual void state(CDS::DataBuffer* params, CDS::DataBuffer* response); 20 | virtual void send(CDS::DataBuffer* params, CDS::DataBuffer* response); 21 | }; 22 | 23 | SerialPort serial; 24 | RFM rfm; 25 | App app; 26 | 27 | USBRFMApp(); 28 | virtual ~USBRFMApp(); 29 | void loop(); 30 | void setup(); 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/USBRFMApp/USBRFMApp.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Pulsartronic 3 | * An Open Source project is a forever Work In Progress, feel free to contribute 4 | * 5 | */ 6 | 7 | #include "USBRFMApp.h" 8 | 9 | USBRFMApp usbRFMApp; 10 | 11 | void setup() { 12 | usbRFMApp.setup(); 13 | } 14 | 15 | void loop() { 16 | usbRFMApp.loop(); 17 | } 18 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/CDS/Array.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | CDS::DataBuffer* CDS::Array::newObject(CDS::DataBuffer* array) { 5 | CDS::DataBuffer* newObject = CDS::Element::newObject(); 6 | CDS::Array::add(array, newObject); 7 | return newObject; 8 | } 9 | 10 | CDS::DataBuffer* CDS::Array::newArray(CDS::DataBuffer* array) { 11 | CDS::DataBuffer* newArray = CDS::Element::newArray(); 12 | CDS::Array::add(array, newArray); 13 | return newArray; 14 | } 15 | 16 | CDS::DataBuffer* CDS::Array::newNumber(CDS::DataBuffer* array) { 17 | CDS::DataBuffer* newNumber = CDS::Element::newNumber(); 18 | CDS::Array::add(array, newNumber); 19 | return newNumber; 20 | } 21 | 22 | CDS::DataBuffer* CDS::Array::add(CDS::DataBuffer* array, CDS::DataBuffer* element) { 23 | CDS::DataBuffer* prev = CDS::Element::last(array); 24 | CDS::DataBuffer* last = CDS::Element::last(element); 25 | CDS::DataBuffer* next = prev->next; 26 | 27 | element->prev = prev; 28 | prev->next = element; 29 | 30 | last->next = next; 31 | if (NULL != next) next->prev = last; 32 | 33 | size_t size = CDS::Element::size(array); 34 | CDS::Element::resize(array, (size_t) (size + 1)); 35 | } 36 | 37 | CDS::DataBuffer* CDS::Array::get(CDS::DataBuffer* array, size_t index) { 38 | CDS::DataBuffer* element = array->next; 39 | for (size_t i = (size_t) 0; i < index; i++) { 40 | CDS::DataBuffer* last = CDS::Element::last(element); 41 | element = last->next; 42 | } 43 | return element; 44 | } 45 | 46 | CDS::Iterator CDS::Array::taketo(CDS::Iterator iterator, size_t index) { 47 | uint8_t initial = iterator.read(); 48 | // uint8_t ET = initial & CDS::TYPE_MASK; // TODO:: there is no check against CDS::ARRAY 49 | size_t hml = (size_t) (initial & ~CDS::TYPE_MASK); 50 | size_t size = (size_t) 0; 51 | for (size_t i = (size_t) 0; i < hml; i++) size = (size << 8) | ((size_t) iterator.read()); 52 | 53 | for (size_t i = (size_t) 0; i < index; i++) { 54 | CDS::Element::last(&iterator); 55 | } 56 | 57 | return iterator; 58 | } 59 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/CDS/DataBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | CDS::DataBuffer::DataBuffer() { 4 | 5 | } 6 | 7 | CDS::DataBuffer::~DataBuffer() { 8 | delete this->next; 9 | } 10 | 11 | void CDS::DataBuffer::resize(size_t size) { 12 | 13 | } 14 | 15 | void CDS::DataBuffer::write(size_t index, uint8_t value) { 16 | 17 | } 18 | 19 | uint8_t CDS::DataBuffer::read(size_t index) { 20 | return (uint8_t) 0; 21 | } 22 | 23 | void CDS::DataBuffer::write(size_t index, uint8_t* buffer, size_t size) { 24 | 25 | } 26 | 27 | CDS::DataBuffer* CDS::DataBuffer::subBuffer(size_t index, size_t size) { 28 | return NULL; 29 | } 30 | 31 | void CDS::DataBuffer::serialize(CDS::Iterator* iterator, size_t size) { 32 | 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/CDS/DynamicBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | CDS::DynamicBuffer::~DynamicBuffer() { 4 | delete[] this->data; 5 | } 6 | 7 | CDS::DynamicBuffer::DynamicBuffer(size_t size) { 8 | this->data = new uint8_t[size]; 9 | } 10 | 11 | void CDS::DynamicBuffer::resize(size_t size) { 12 | delete[] this->data; 13 | this->data = new uint8_t[size]; 14 | } 15 | 16 | void CDS::DynamicBuffer::write(size_t index, uint8_t value) { 17 | this->data[index] = value; 18 | } 19 | 20 | uint8_t CDS::DynamicBuffer::read(size_t index) { 21 | return this->data[index]; 22 | } 23 | 24 | 25 | void CDS::DynamicBuffer::write(size_t index, uint8_t* data, size_t size) { 26 | // memcpy ?? 27 | for (size_t i = (size_t) 0; i < size; i++) { 28 | this->data[index + i] = data[i]; 29 | } 30 | } 31 | 32 | CDS::DataBuffer* CDS::DynamicBuffer::subBuffer(size_t index, size_t size) { 33 | uint8_t* subbuffer = this->data + index; 34 | CDS::DataBuffer* subBuffer = new CDS::StaticBuffer(subbuffer); 35 | return subBuffer; 36 | } 37 | 38 | void CDS::DynamicBuffer::serialize(CDS::Iterator* iterator, size_t size) { 39 | iterator->write(this->data, size); 40 | } 41 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/CDS/EEPROMBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | CDS::EEPROMBuffer::~EEPROMBuffer() { 4 | 5 | } 6 | 7 | CDS::EEPROMBuffer::EEPROMBuffer(size_t start) : start(start) { 8 | 9 | } 10 | 11 | void CDS::EEPROMBuffer::resize(size_t size) { 12 | 13 | } 14 | 15 | void CDS::EEPROMBuffer::write(size_t index, uint8_t value) { 16 | uint8_t storedValue = EEPROM.read(index); 17 | if (storedValue != value) { 18 | EEPROM.write(this->start + index, value); 19 | } 20 | } 21 | 22 | uint8_t CDS::EEPROMBuffer::read(size_t index) { 23 | uint8_t value = EEPROM.read(this->start + index); 24 | return value; 25 | } 26 | 27 | 28 | void CDS::EEPROMBuffer::write(size_t index, uint8_t* data, size_t size) { 29 | for (size_t i = (size_t) 0; i < size; i++) { 30 | uint8_t value = data[i]; 31 | this->write(index + i, value); 32 | } 33 | } 34 | 35 | CDS::DataBuffer* CDS::EEPROMBuffer::subBuffer(size_t index, size_t size) { 36 | CDS::DataBuffer* subBuffer = new EEPROMBuffer(this->start + index); 37 | return subBuffer; 38 | } 39 | 40 | void CDS::EEPROMBuffer::serialize(CDS::Iterator* iterator, size_t size) { 41 | for (size_t i = (size_t) 0; i < size; i++) { 42 | uint8_t value = this->read(i); 43 | iterator->write(value); 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/CDS/Iterator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | CDS::Iterator::Iterator() { 4 | 5 | } 6 | 7 | CDS::Iterator::Iterator(CDS::DataBuffer* buffer, size_t size) : buffer(buffer), size(size) { 8 | 9 | } 10 | 11 | size_t CDS::Iterator::available() { 12 | size_t available = (this->size >= this->index) ? (this->size - this->index) : (size_t) 0; 13 | return available; 14 | } 15 | 16 | void CDS::Iterator::write(uint8_t value) { 17 | this->buffer->write(this->index++, value); 18 | } 19 | 20 | void CDS::Iterator::write(uint8_t* data, size_t size) { 21 | this->buffer->write(this->index, data, size); 22 | this->index += size; 23 | } 24 | 25 | uint8_t CDS::Iterator::peek() { 26 | return this->buffer->read(this->index); 27 | } 28 | 29 | uint8_t CDS::Iterator::read() { 30 | return this->buffer->read(this->index++); 31 | } 32 | 33 | CDS::DataBuffer* CDS::Iterator::subBuffer(size_t size) { 34 | CDS::DataBuffer* subBuffer = this->buffer->subBuffer(this->index, size); 35 | this->index += size; 36 | return subBuffer; 37 | } 38 | 39 | void CDS::Iterator::skip(size_t count) { 40 | size_t available = this->available(); 41 | this->index += min(count, available); 42 | } 43 | 44 | 45 | void CDS::Iterator::reset() { 46 | this->index = (size_t) 0; 47 | } 48 | 49 | size_t CDS::Iterator::readSize(uint8_t initial) { 50 | size_t hml = (size_t) (initial & ~CDS::TYPE_MASK); 51 | size_t size = (size_t) 0; 52 | for (size_t i = (size_t) 0; i < hml; i++) { 53 | size = (size << 8) | ((size_t) this->read()); 54 | } 55 | return size; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/CDS/Number.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void CDS::Number::serialize(DataBuffer* element, Iterator* iterator) { 4 | bool isNumber = CDS::Element::isNumber(element); 5 | if (isNumber) { 6 | size_t hml = CDS::Element::hml(element); 7 | size_t size = CDS::Element::size(element); 8 | for (size_t i = (size_t) 0; i < size; i++) { 9 | uint8_t value = element->read((size_t) (1 + hml + i)); 10 | iterator->write(value); 11 | } 12 | } 13 | }; 14 | 15 | void CDS::Number::setChars(CDS::DataBuffer* number, const uint8_t* name) { 16 | size_t strsize = (size_t) strlen((const char*) name); 17 | CDS::Element::resize(number, strsize); 18 | size_t HML = CDS::Element::hml(number); 19 | for (size_t i = (size_t) 0; i < strsize; i++) { 20 | uint8_t value = (uint8_t) name[i]; 21 | number->write((size_t) (1 + HML + i), value); 22 | } 23 | } 24 | 25 | void CDS::Number::setData(CDS::DataBuffer* number, CDS::DataBuffer* data) { 26 | size_t datasize = CDS::Element::size(data); 27 | CDS::Element::resize(number, datasize); 28 | size_t numbersize = CDS::Element::size(number); 29 | size_t size = min(datasize, numbersize); 30 | size_t hmla = CDS::Element::hml(number); 31 | size_t hmlb = CDS::Element::hml(data); 32 | for (size_t i = (size_t) 0; i < size; i++) { 33 | uint8_t value = data->read(1 + hmlb + i); 34 | number->write((size_t) (1 + hmla + i), value); 35 | } 36 | } 37 | 38 | bool CDS::Number::cmp(CDS::DataBuffer* number, const uint8_t* name) { 39 | size_t size = CDS::Element::size(number); 40 | size_t HML = CDS::Element::hml(number); 41 | size_t strsize = (size_t) strlen((const char*) name); 42 | bool equals = (size == strsize); 43 | if (equals) { 44 | for (size_t i = (size_t) 0; i < size && equals; i++) { 45 | uint8_t d = number->read((size_t) (1 + HML + i)); 46 | uint8_t n = name[i]; 47 | equals = equals && (d == n); 48 | } 49 | } 50 | return equals; 51 | } 52 | 53 | bool CDS::Number::cmp(CDS::DataBuffer* a, CDS::DataBuffer* b) { 54 | bool equals = false; 55 | if (NULL != a && NULL != b) { 56 | size_t asize = CDS::Element::size(a); 57 | size_t ahml = CDS::Element::hml(a); 58 | size_t bsize = CDS::Element::size(b); 59 | size_t bhml = CDS::Element::hml(b); 60 | equals = (asize == bsize); 61 | if (equals) { 62 | for (size_t i = (size_t) 0; i < asize && equals; i++) { 63 | uint8_t av = a->read((size_t) (1 + ahml + i)); 64 | uint8_t bv = b->read((size_t) (1 + bhml + i)); 65 | equals = equals && (av == bv); 66 | } 67 | } 68 | } 69 | return equals; 70 | } 71 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/CDS/Object.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | CDS::DataBuffer* CDS::Object::newObject(CDS::DataBuffer* object, const uint8_t* name) { 5 | CDS::DataBuffer* newObject = CDS::Element::newObject(); 6 | CDS::Object::set(object, name, newObject); 7 | return newObject; 8 | } 9 | 10 | CDS::DataBuffer* CDS::Object::newArray(CDS::DataBuffer* object, const uint8_t* name) { 11 | CDS::DataBuffer* newArray = CDS::Element::newArray(); 12 | CDS::Object::set(object, name, newArray); 13 | return newArray; 14 | } 15 | 16 | CDS::DataBuffer* CDS::Object::newNumber(CDS::DataBuffer* object, const uint8_t* name) { 17 | CDS::DataBuffer* newNumber = CDS::Element::newNumber(); 18 | CDS::Object::set(object, name, newNumber); 19 | return newNumber; 20 | } 21 | 22 | CDS::DataBuffer* CDS::Object::key(DataBuffer* object, size_t index) { 23 | CDS::DataBuffer* key = object->next; 24 | for (size_t i = (size_t) 0; i < index; i++) { 25 | CDS::DataBuffer* last = CDS::Element::last(key->next); 26 | key = last->next; 27 | } 28 | return key; 29 | } 30 | 31 | CDS::DataBuffer* CDS::Object::get(DataBuffer* object, const uint8_t* name) { 32 | CDS::DataBuffer* element = NULL; 33 | size_t size = CDS::Element::size(object); 34 | for (size_t i = (size_t) 0; i < size; i++) { 35 | CDS::DataBuffer* key = CDS::Object::key(object, i); 36 | bool equals = CDS::Number::cmp(key, name); 37 | if (equals) { 38 | element = key->next; 39 | break; 40 | } 41 | } 42 | return element; 43 | } 44 | 45 | void CDS::Object::set(CDS::DataBuffer* object, const uint8_t* name, CDS::DataBuffer* value) { 46 | CDS::DataBuffer* key = CDS::Element::newNumber(); 47 | CDS::Number::setChars(key, name); 48 | CDS::Object::set(object, key, value); 49 | } 50 | 51 | void CDS::Object::set(CDS::DataBuffer* object, CDS::DataBuffer* key, CDS::DataBuffer* value) { 52 | // TODO:: check for key existance !!! 53 | // CDS::DataBuffer* saved = CDS::Object::get(object, name); 54 | 55 | CDS::DataBuffer* last = CDS::Element::last(value); 56 | CDS::DataBuffer* prev = CDS::Element::last(object); 57 | CDS::DataBuffer* next = prev->next; 58 | 59 | key->prev = prev; 60 | prev->next = key; 61 | 62 | value->prev = key; 63 | key->next = value; 64 | 65 | last->next = next; 66 | if (NULL != next) next->prev = last; 67 | 68 | size_t size = CDS::Element::size(object); 69 | CDS::Element::resize(object, (size_t) (size + 1)); 70 | } 71 | 72 | /* 73 | CDS::Iterator CDS::Object::taketo(CDS::Iterator storage, const uint8_t* name) { 74 | // TODO:: there is no check against CDS::OBJECT 75 | uint8_t initial = storage.read(); 76 | size_t size = storage.readSize(initial); 77 | 78 | for (size_t i = (size_t) 0; i < size; i++) { 79 | CDS::DataBuffer* key = CDS::Element::nextElement(&storage); 80 | bool equals = CDS::Number::cmp(key, name); 81 | delete key; 82 | if (equals) { 83 | break; 84 | } else { 85 | CDS::Element::last(&storage); 86 | } 87 | } 88 | return storage; 89 | } 90 | */ 91 | 92 | CDS::Iterator CDS::Object::taketo(CDS::Iterator storage, const uint8_t* name) { 93 | CDS::DataBuffer* key = CDS::Element::newNumber(name); 94 | storage = CDS::Object::taketo(storage, key); 95 | delete key; 96 | return storage; 97 | } 98 | 99 | 100 | CDS::Iterator CDS::Object::taketo(CDS::Iterator storage, CDS::DataBuffer* key) { 101 | // TODO:: there is no check against CDS::OBJECT 102 | uint8_t initial = storage.read(); 103 | size_t size = storage.readSize(initial); 104 | for (size_t i = (size_t) 0; i < size; i++) { 105 | CDS::DataBuffer* storedKey = CDS::Element::nextElement(&storage); 106 | bool equals = CDS::Number::cmp(key, storedKey); 107 | delete storedKey; 108 | if (equals) { 109 | break; 110 | } else { 111 | CDS::Element::last(&storage); 112 | } 113 | } 114 | return storage; 115 | } 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/CDS/PROGMEMBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | CDS::PROGMEMBuffer::~PROGMEMBuffer() { 4 | 5 | } 6 | 7 | CDS::PROGMEMBuffer::PROGMEMBuffer(uint8_t* data, size_t start) : data(data), start(start) { 8 | 9 | } 10 | 11 | void CDS::PROGMEMBuffer::resize(size_t size) { 12 | 13 | } 14 | 15 | void CDS::PROGMEMBuffer::write(size_t index, uint8_t value) { 16 | 17 | } 18 | 19 | uint8_t CDS::PROGMEMBuffer::read(size_t index) { 20 | uint8_t value = pgm_read_byte(this->data + this->start + index); 21 | return value; 22 | } 23 | 24 | 25 | void CDS::PROGMEMBuffer::write(size_t index, uint8_t* data, size_t size) { 26 | 27 | } 28 | 29 | CDS::DataBuffer* CDS::PROGMEMBuffer::subBuffer(size_t index, size_t size) { 30 | CDS::DataBuffer* subBuffer = new PROGMEMBuffer(this->data, this->start + index); 31 | return subBuffer; 32 | } 33 | 34 | void CDS::PROGMEMBuffer::serialize(CDS::Iterator* iterator, size_t size) { 35 | 36 | } 37 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/CDS/StaticBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | CDS::StaticBuffer::~StaticBuffer() { 4 | 5 | } 6 | 7 | CDS::StaticBuffer::StaticBuffer(uint8_t* data) : data(data) { 8 | 9 | } 10 | 11 | void CDS::StaticBuffer::resize(size_t size) { 12 | 13 | } 14 | 15 | void CDS::StaticBuffer::write(size_t index, uint8_t value) { 16 | this->data[index] = value; 17 | } 18 | 19 | uint8_t CDS::StaticBuffer::read(size_t index) { 20 | return this->data[index]; 21 | } 22 | 23 | void CDS::StaticBuffer::write(size_t index, uint8_t* data, size_t size) { 24 | // memcpy ?? 25 | for (size_t i = (size_t) 0; i < size; i++) { 26 | this->data[index + i] = data[i]; 27 | } 28 | } 29 | 30 | CDS::DataBuffer* CDS::StaticBuffer::subBuffer(size_t index, size_t size) { 31 | uint8_t* subbuffer = this->data + index; 32 | CDS::DataBuffer* subBuffer = new CDS::StaticBuffer(subbuffer); 33 | return subBuffer; 34 | } 35 | 36 | void CDS::StaticBuffer::serialize(CDS::Iterator* iterator, size_t size) { 37 | iterator->write(this->data, size); 38 | } 39 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/CDS/StreamBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | CDS::StreamBuffer::~StreamBuffer() { 4 | 5 | } 6 | 7 | CDS::StreamBuffer::StreamBuffer(Stream* stream) : stream(stream) { 8 | 9 | } 10 | 11 | void CDS::StreamBuffer::write(size_t index, uint8_t value) { 12 | this->stream->write(value); 13 | this->stream->flush(); 14 | } 15 | 16 | void CDS::StreamBuffer::write(size_t index, uint8_t* buffer, size_t size) { 17 | this->stream->write(buffer, (size_t) size); 18 | this->stream->flush(); 19 | } 20 | 21 | uint8_t CDS::StreamBuffer::read(size_t index) { 22 | return this->stream->read(); 23 | } 24 | 25 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/DataChannel/DataChannel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | DataChannel::DataChannel() { 4 | 5 | } 6 | 7 | DataChannel::~DataChannel() { 8 | 9 | } 10 | 11 | void DataChannel::loop() { 12 | 13 | } 14 | 15 | void DataChannel::addHandler(DataChannel::Handler* handler) { 16 | this->handlers->add(handler); 17 | } 18 | 19 | int DataChannel::send(CDS::DataBuffer* data) { 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/DataChannel/DataChannel.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifndef __DataChannel__ 5 | #define __DataChannel__ 6 | 7 | class DataChannel { 8 | public: 9 | 10 | class Handler { 11 | public: 12 | DS::List* channels = new DS::List(); 13 | void addDataChannel(DataChannel* dataChannel); 14 | virtual void onData(DataChannel* dataChannel, CDS::DataBuffer* data) = 0; 15 | }; 16 | 17 | DS::List* handlers = new DS::List(); 18 | 19 | DataChannel(); 20 | virtual ~DataChannel(); 21 | 22 | virtual void loop(); 23 | virtual int send(CDS::DataBuffer* data); 24 | void addHandler(DataChannel::Handler* handler); 25 | }; 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/DataChannel/Handler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void DataChannel::Handler::addDataChannel(DataChannel* channel) { 4 | channel->addHandler(this); 5 | this->channels->add(channel); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/DataStructure/DS.h: -------------------------------------------------------------------------------- 1 | #ifndef __DS__ 2 | #define __DS__ 3 | 4 | #include 5 | 6 | namespace DS { // DS : Data Structure 7 | template class List { 8 | public: 9 | T* buffer = new T[0]; 10 | uint32_t length = 0u; 11 | virtual ~List() { delete[] this->buffer; } 12 | 13 | T get(uint32_t index){ 14 | T element = this->buffer[index]; 15 | return element; 16 | } 17 | 18 | void add(T element) { 19 | uint16_t newLength = this->length + 1; 20 | T* newBuffer = new T[newLength]; 21 | for (uint16_t i = 0u; i < this->length; i++) { 22 | newBuffer[i] = this->buffer[i]; 23 | } 24 | newBuffer[this->length] = element; 25 | delete[] this->buffer; 26 | this->length = newLength; 27 | this->buffer = newBuffer; 28 | } 29 | 30 | T shift() { 31 | T element = this->get(0); 32 | this->removeAt(0); 33 | return element; 34 | } 35 | 36 | void resize(uint32_t length) { 37 | T* newBuffer = new T[length]; 38 | for (uint32_t i = (uint32_t) 0; i < min(this->length, length); i++) { 39 | newBuffer[i] = this->buffer[i]; 40 | } 41 | delete[] this->buffer; 42 | this->length = length; 43 | this->buffer = newBuffer; 44 | } 45 | 46 | void removeAt(uint32_t index) { 47 | if (0 <= index && index < this->length) { 48 | uint32_t newLength = this->length - 1; 49 | T* newBuffer = new T[newLength]; 50 | uint32_t j = (uint32_t) 0; 51 | for (uint32_t i = (uint32_t) 0; i < this->length; i++) { 52 | if (i != index) { 53 | newBuffer[j++] = this->buffer[i]; 54 | } 55 | } 56 | delete[] this->buffer; 57 | this->length = newLength; 58 | this->buffer = newBuffer; 59 | } 60 | } 61 | 62 | int16_t indexOf(T element) { 63 | int32_t index = (int32_t) -1; 64 | for (int32_t i = 0ul; (i < this->length) && (0 > index); i++) { 65 | T saved = this->buffer[i]; 66 | if (element == saved) { 67 | index = i; 68 | } 69 | } 70 | return index; 71 | } 72 | }; 73 | } 74 | #endif 75 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/DataStructure/KeyValueMap.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef __KeyValueMap__ 4 | #define __KeyValueMap__ 5 | 6 | template class KeyValue { 7 | public: 8 | char* key; 9 | T* value = NULL; 10 | 11 | virtual ~KeyValue() { 12 | delete[] this->key; 13 | } 14 | 15 | KeyValue(const char* key, T* value) { 16 | int length = strlen(key); 17 | this->key = new char[length + 1]; 18 | memcpy(this->key, key, length + 1); 19 | this->value = value; 20 | } 21 | }; 22 | 23 | template class KeyValueMap { 24 | public: 25 | uint16_t length = 0u; 26 | KeyValue** keyValues = new KeyValue*[0]; 27 | 28 | virtual ~KeyValueMap() { 29 | for (uint16_t i = 0u; i < this->length; i++) { 30 | KeyValue* keyValue = this->keyValues[i]; 31 | delete keyValue; 32 | } 33 | delete[] this->keyValues; 34 | } 35 | 36 | KeyValueMap() { 37 | 38 | } 39 | 40 | T* get(CDS::DataBuffer* number) { 41 | T* value = NULL; 42 | KeyValue* skeyValue = this->key(number); 43 | if (NULL != skeyValue) { 44 | value = skeyValue->value; 45 | } 46 | return value; 47 | } 48 | 49 | KeyValue* key(CDS::DataBuffer* number) { 50 | KeyValue* keyValue = NULL; 51 | for (uint16_t i = 0u; (i < this->length) && (NULL == keyValue); i++) { 52 | KeyValue* skeyValue = this->keyValues[i]; 53 | if (NULL != skeyValue) { 54 | bool equals = CDS::Number::cmp(number, (const uint8_t*) skeyValue->key); 55 | if (equals) { 56 | keyValue = skeyValue; 57 | } 58 | } 59 | } 60 | return keyValue; 61 | } 62 | 63 | KeyValue* key(const char* key) { 64 | KeyValue* keyValue = NULL; 65 | for (uint16_t i = 0u; (i < this->length) && (NULL == keyValue); i++) { 66 | KeyValue* skeyValue = this->keyValues[i]; 67 | if (NULL != skeyValue) { 68 | // TODO:: binary search ??, does order matters ?? 69 | if (0 == strcmp(key, skeyValue->key)) { 70 | keyValue = skeyValue; 71 | } 72 | } 73 | } 74 | return keyValue; 75 | } 76 | 77 | void set(String& key, T* value) { 78 | const char* ckey = key.c_str(); 79 | this->set(ckey, value); 80 | } 81 | 82 | void set(const char* key, T* value) { 83 | KeyValue* skeyValue = this->key(key); 84 | if (NULL != skeyValue) { 85 | skeyValue->value = value; 86 | } else { 87 | KeyValue** newKeyValues = new KeyValue*[this->length + 1]; 88 | for (unsigned int i = 0u; i < this->length; i++) { 89 | newKeyValues[i] = this->keyValues[i]; 90 | } 91 | newKeyValues[this->length] = new KeyValue(key, value); 92 | delete[] this->keyValues; 93 | this->keyValues = newKeyValues; 94 | this->length += 1u; 95 | } 96 | } 97 | 98 | T* get(const char* key) { 99 | T* value = NULL; 100 | KeyValue* skeyValue = this->key(key); 101 | if (NULL != skeyValue) { 102 | value = skeyValue->value; 103 | } 104 | return value; 105 | } 106 | 107 | void remove(char* key) { 108 | // TODO:: 109 | } 110 | }; 111 | 112 | #endif 113 | 114 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/Node/Node.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void Node_state(Node* cdNode, CDS::DataBuffer* params, CDS::DataBuffer* response) { 4 | cdNode->state(params, response); 5 | } 6 | 7 | void Node_save(Node* cdNode, CDS::DataBuffer* params, CDS::DataBuffer* response) { 8 | cdNode->save(params, response); 9 | } 10 | 11 | 12 | Node::Node(Node* parent, const char* name) : parent(parent) { 13 | this->name = String(name); 14 | this->nodes = new KeyValueMap(); 15 | this->methods = new KeyValueMap(); 16 | 17 | Method* state = new Node::Method(this, Node_state); 18 | this->methods->set(S("state"), state); 19 | 20 | Method* save = new Node::Method(this, Node_save); 21 | this->methods->set(S("save"), save); 22 | } 23 | 24 | Node::~Node() { 25 | delete this->nodes; 26 | 27 | Method* state = this->methods->get(S("state")); 28 | delete state; 29 | 30 | Method* save = this->methods->get(S("save")); 31 | delete save; 32 | 33 | delete this->methods; 34 | } 35 | 36 | CDS::Iterator Node::storage() { 37 | return CDS::Object::taketo(this->parent->storage(), (const uint8_t*) this->name.c_str()); 38 | } 39 | 40 | void Node::from(CDS::DataBuffer* params) { 41 | 42 | } 43 | 44 | void Node::to(CDS::DataBuffer* params) { 45 | 46 | } 47 | 48 | void Node::applySettings() { 49 | 50 | } 51 | 52 | void Node::save(CDS::DataBuffer* params, CDS::DataBuffer* response) { 53 | this->from(params); 54 | this->applySettings(); 55 | yield(); 56 | this->state(params, response); 57 | } 58 | 59 | void Node::oncommand(CDS::DataBuffer* params, CDS::DataBuffer* response) { 60 | size_t size = CDS::Element::size(params); 61 | for (size_t i = (size_t) 0; i < size; i++) { 62 | CDS::DataBuffer* key = CDS::Object::key(params, i); 63 | if (NULL != key) { 64 | if (NULL != key->next) { 65 | bool isObject = CDS::Element::isObject(key->next); 66 | if (isObject) { 67 | CDS::DataBuffer* iparams = key->next; 68 | Node* implementer = this->nodes->get(key); 69 | Method* method = this->methods->get(key); 70 | if (NULL != implementer) { 71 | implementer->oncommand(iparams, response); 72 | } else if (NULL != method) { 73 | method->call(iparams, response); 74 | } 75 | } 76 | } 77 | } 78 | } 79 | } 80 | 81 | void Node::command(CDS::DataBuffer* command) { 82 | this->parent->command(command); 83 | } 84 | 85 | CDS::DataBuffer* Node::rootIT(CDS::DataBuffer* root) { 86 | CDS::DataBuffer* parentObject = this->parent->rootIT(root); 87 | CDS::DataBuffer* createdObject = CDS::Object::get(parentObject, (const uint8_t*) this->name.c_str()); 88 | if (NULL == createdObject) { 89 | createdObject = CDS::Object::newObject(parentObject, (const uint8_t*) this->name.c_str()); 90 | } 91 | return createdObject; 92 | } 93 | 94 | void Node::state(CDS::DataBuffer* params, CDS::DataBuffer* response) { 95 | 96 | } 97 | 98 | void Node::log(String& text) { 99 | /* 100 | DynamicJsonDocument rootDocument(512); 101 | CDS::DataBuffer command = rootDocument.to(); 102 | CDS::DataBuffer object = this->rootIT(command); 103 | CDS::DataBuffer log = object.createNestedObject("log"); 104 | log["text"] = text; 105 | log["tstm"] = sntp_get_current_timestamp(); 106 | this->command(command); 107 | */ 108 | } 109 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/Node/Node.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifndef __Node__ 6 | #define __Node__ 7 | 8 | class Node { 9 | public: 10 | class Method { 11 | public: 12 | Node* cdNode = NULL; 13 | void (*method) (Node* cdNode, CDS::DataBuffer*, CDS::DataBuffer*); 14 | 15 | Method(Node* cdNode, void (*method) (Node* cdNode, CDS::DataBuffer*, CDS::DataBuffer*)) { 16 | this->cdNode = cdNode; 17 | this->method = method; 18 | } 19 | 20 | void call(CDS::DataBuffer* params, CDS::DataBuffer* response) { 21 | this->method(this->cdNode, params, response); 22 | } 23 | }; 24 | 25 | Node* parent = NULL; 26 | String name; 27 | KeyValueMap* nodes = NULL; 28 | KeyValueMap* methods = NULL; 29 | 30 | Node(Node* parent, const char* name); 31 | virtual ~Node(); 32 | 33 | virtual void from(CDS::DataBuffer* params); 34 | virtual void to(CDS::DataBuffer* params); // DEPRECATED 35 | virtual void applySettings(); 36 | virtual void save(CDS::DataBuffer* params, CDS::DataBuffer* response); 37 | virtual void oncommand(CDS::DataBuffer* params, CDS::DataBuffer* response); 38 | virtual void command(CDS::DataBuffer* command); 39 | virtual CDS::DataBuffer* rootIT(CDS::DataBuffer* root); 40 | virtual void state(CDS::DataBuffer* params, CDS::DataBuffer* response); 41 | virtual void log(String& text); 42 | 43 | virtual CDS::Iterator storage(); 44 | }; 45 | 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/Node/RootNode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | RootNode::RootNode(Node* parent, const char* name) : Node(parent, name) { 5 | 6 | } 7 | 8 | RootNode::~RootNode() { 9 | 10 | } 11 | 12 | void RootNode::setup() { 13 | 14 | } 15 | 16 | void RootNode::loop() { 17 | 18 | } 19 | 20 | void RootNode::onData(DataChannel* dataChannel, CDS::DataBuffer* command) { 21 | bool isObject = CDS::Element::isObject(command); 22 | if (isObject) { 23 | CDS::DataBuffer* response = CDS::Element::newObject(); 24 | this->oncommand(command, response); 25 | this->send(response); 26 | delete response; 27 | } 28 | } 29 | 30 | void RootNode::command(CDS::DataBuffer* command) { 31 | this->send(command); 32 | } 33 | 34 | void RootNode::send(CDS::DataBuffer* command) { 35 | for (int i = 0; i < this->channels->length; i++) { 36 | DataChannel* channel = this->channels->get(i); 37 | channel->send(command); 38 | yield(); 39 | } 40 | } 41 | 42 | CDS::DataBuffer* RootNode::rootIT(CDS::DataBuffer* root) { 43 | return root; 44 | } 45 | 46 | CDS::Iterator RootNode::storage() { 47 | return this->storageIterator; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/Node/RootNode.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifndef __RootNode__ 6 | #define __RootNode__ 7 | 8 | class RootNode : public Node, public DataChannel::Handler { 9 | public: 10 | 11 | CDS::Iterator storageIterator; 12 | 13 | RootNode(Node* parent, const char* name); 14 | virtual ~RootNode(); 15 | 16 | virtual void setup(); 17 | virtual void loop(); 18 | virtual void command(CDS::DataBuffer* command); 19 | virtual CDS::DataBuffer* rootIT(CDS::DataBuffer* root); 20 | virtual void onData(DataChannel* dataChannel, CDS::DataBuffer* data); 21 | virtual CDS::Iterator storage(); 22 | 23 | void send(CDS::DataBuffer* command); 24 | }; 25 | 26 | #endif 27 | 28 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/RFM/Channel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | RFM::Channel::Channel(RFM* rfm) : rfm(rfm) { 4 | 5 | } 6 | 7 | void RFM::Channel::loop() { 8 | int size = LoRa.parsePacket(); 9 | if (size) { 10 | CDS::DynamicBuffer* element = new CDS::DynamicBuffer((size_t) (2 + size)); 11 | element->write((size_t) 0, (uint8_t) (CDS::BINARY | (uint8_t) 1)); 12 | element->write((size_t) 1, (uint8_t) size); 13 | 14 | int available = LoRa.available(); 15 | uint16_t i = 0; 16 | while (available && (i < size)) { 17 | element->data[2 + i++] = LoRa.read(); 18 | available = LoRa.available(); 19 | } 20 | 21 | for (uint16_t i = 0u; i < this->handlers->length; i++) { 22 | DataChannel::Handler* handler = this->handlers->get(i); 23 | handler->onData(this, element); 24 | } 25 | delete element; 26 | } 27 | } 28 | 29 | int RFM::Channel::send(CDS::DataBuffer* command) { 30 | int sent = 0; 31 | if (this->rfm->active) { 32 | // TODO:: make more checks against transmission 33 | sent = LoRa.beginPacket(); 34 | if (sent) { 35 | CDS::StreamBuffer* streamBuffer = new CDS::StreamBuffer(&LoRa); 36 | CDS::Iterator* iterator = new CDS::Iterator(streamBuffer, 0); 37 | CDS::Number::serialize(command, iterator); 38 | sent = iterator->index; 39 | delete streamBuffer; 40 | delete iterator; 41 | // TODO:: should we use async ending ?? !!!potential dead-lock!!! 42 | // if the RFM is not working properly, here it locks 43 | int end = LoRa.endPacket(); 44 | if (0 == end) { 45 | sent = 0; 46 | } 47 | } 48 | } 49 | return sent; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/RFM/RFM.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | RFM::RFM(Node* parent, const char* name) : channel(this), Node(parent, name) { 4 | 5 | } 6 | 7 | RFM::~RFM() { 8 | 9 | } 10 | 11 | void RFM::setup() { 12 | this->applySettings(); 13 | } 14 | 15 | void RFM::loop() { 16 | this->channel.loop(); 17 | } 18 | 19 | void RFM::applySettings() { 20 | // This call is optional, it is needed only if you have to change the default SPI interface used 21 | // LoRa.setSPI(spi); 22 | 23 | CDS::Iterator storage = this->storage(); 24 | 25 | CDS::Iterator pinsStorage = CDS::Object::taketo(storage, K("pins")); 26 | CDS::Iterator nssStorage = CDS::Object::taketo(pinsStorage, K("nss")); 27 | CDS::DataBuffer* savedNss = CDS::Element::nextElement(&nssStorage); 28 | uint8_t nss = CDS::Number::value(savedNss); 29 | delete savedNss; 30 | CDS::Iterator rstStorage = CDS::Object::taketo(pinsStorage, K("rst")); 31 | CDS::DataBuffer* savedRst = CDS::Element::nextElement(&rstStorage); 32 | uint8_t rst = CDS::Number::value(savedRst); 33 | delete savedRst; 34 | CDS::Iterator dioStorage = CDS::Object::taketo(pinsStorage, K("dio")); 35 | CDS::Iterator dio0Storage = CDS::Array::taketo(dioStorage, 0); 36 | CDS::DataBuffer* savedDio0 = CDS::Element::nextElement(&dio0Storage); 37 | uint8_t dio0 = CDS::Number::value(savedDio0); 38 | delete savedDio0; 39 | LoRa.setPins(nss, rst, dio0); 40 | 41 | CDS::Iterator freqStorage = CDS::Object::taketo(storage, K("freq")); 42 | CDS::Iterator currStorage = CDS::Object::taketo(freqStorage, K("curr")); 43 | CDS::DataBuffer* savedCurr = CDS::Element::nextElement(&currStorage); 44 | uint32_t curr = CDS::Number::value(savedCurr); 45 | delete savedCurr; 46 | this->active = LoRa.begin(curr); 47 | 48 | if (this->active) { 49 | CDS::Iterator txpwStorage = CDS::Object::taketo(storage, K("txpw")); 50 | CDS::DataBuffer* savedTxpw = CDS::Element::nextElement(&txpwStorage); 51 | uint8_t txpw = CDS::Number::value(savedTxpw); 52 | delete savedTxpw; 53 | LoRa.setTxPower(txpw); 54 | 55 | CDS::Iterator sfacStorage = CDS::Object::taketo(storage, K("sfac")); 56 | CDS::DataBuffer* savedSfac = CDS::Element::nextElement(&sfacStorage); 57 | uint8_t sfac = CDS::Number::value(savedSfac); 58 | delete savedSfac; 59 | LoRa.setSpreadingFactor(sfac); 60 | 61 | CDS::Iterator sbwStorage = CDS::Object::taketo(storage, K("sbw")); 62 | CDS::DataBuffer* savedSbw = CDS::Element::nextElement(&sbwStorage); 63 | uint32_t sbw = CDS::Number::value(savedSbw); 64 | delete savedSbw; 65 | LoRa.setSignalBandwidth(sbw); 66 | 67 | CDS::Iterator cratStorage = CDS::Object::taketo(storage, K("crat")); 68 | CDS::DataBuffer* savedCrat = CDS::Element::nextElement(&cratStorage); 69 | uint8_t crat = CDS::Number::value(savedCrat); 70 | delete savedCrat; 71 | LoRa.setCodingRate4(crat); 72 | 73 | CDS::Iterator plengthStorage = CDS::Object::taketo(storage, K("plength")); 74 | CDS::DataBuffer* savedPlength = CDS::Element::nextElement(&plengthStorage); 75 | uint8_t plength = CDS::Number::value(savedPlength); 76 | delete savedPlength; 77 | LoRa.setPreambleLength(plength); 78 | 79 | CDS::Iterator swStorage = CDS::Object::taketo(storage, K("sw")); 80 | CDS::DataBuffer* savedSw = CDS::Element::nextElement(&swStorage); 81 | uint8_t sw = CDS::Number::value(savedSw); 82 | delete savedSw; 83 | LoRa.setSyncWord(sw); 84 | 85 | CDS::Iterator crcStorage = CDS::Object::taketo(storage, K("crc")); 86 | CDS::DataBuffer* savedCrc = CDS::Element::nextElement(&crcStorage); 87 | uint8_t crc = CDS::Number::value(savedCrc); 88 | delete savedCrc; 89 | if (crc) { 90 | LoRa.enableCrc(); 91 | } else { 92 | LoRa.disableCrc(); 93 | } 94 | 95 | CDS::Iterator iiqStorage = CDS::Object::taketo(storage, K("iiq")); 96 | CDS::DataBuffer* savedIiq = CDS::Element::nextElement(&iiqStorage); 97 | uint8_t iiq = CDS::Number::value(savedIiq); 98 | delete savedIiq; 99 | if (iiq) { 100 | LoRa.enableInvertIQ(); 101 | } else { 102 | LoRa.disableInvertIQ(); 103 | } 104 | } 105 | 106 | yield(); 107 | } 108 | 109 | void RFM::state(CDS::DataBuffer* params, CDS::DataBuffer* response) { 110 | CDS::DataBuffer* object = this->rootIT(response); 111 | CDS::DataBuffer* state = CDS::Object::newObject(object, K("state")); 112 | 113 | CDS::DataBuffer* status = CDS::Object::newNumber(state, K("status")); 114 | CDS::Number::set(status, this->active); 115 | 116 | CDS::Iterator storage = this->storage(); 117 | CDS::DataBuffer* config = CDS::Element::nextElement(&storage); 118 | CDS::Object::set(state, K("config"), config); 119 | } 120 | 121 | void RFM::from(CDS::DataBuffer* params) { 122 | CDS::Iterator storage = this->storage(); 123 | CDS::Element::fill(storage, params); 124 | #ifdef ESP8266 125 | EEPROM.commit(); 126 | #endif 127 | } 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/RFM/RFM.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #ifndef __RFM__ 7 | #define __RFM__ 8 | 9 | class RFM : public Node { 10 | public: 11 | 12 | class Channel : public DataChannel { 13 | public: 14 | RFM* rfm = NULL; 15 | Channel(RFM* rfm); 16 | virtual void loop(); 17 | virtual int send(CDS::DataBuffer* command); 18 | }; 19 | /* 20 | class Pins { 21 | public: 22 | uint8_t miso = 12; 23 | uint8_t mosi = 13; 24 | uint8_t sck = 14; 25 | uint8_t nss = 8; 26 | uint8_t rst = 7; 27 | int8_t dio[6] = {5, -1, -1, -1, -1, -1}; 28 | }; 29 | /* 30 | class Settings { 31 | public: 32 | 33 | class Frequency { 34 | public: 35 | long curr = 868300000l; // current frequency in Hz 36 | long min = 858000000l; // min frequency in Hz 37 | long max = 878000000l; // max frequency in Hz 38 | }; 39 | 40 | Frequency freq; 41 | uint8_t txpw = (uint8_t) 17; // tx power 42 | uint8_t sfac = (uint8_t) 7; // spreading factor 43 | long sbw = 125E3; // SignalBandwidth 44 | uint8_t crat = (uint8_t) 5; // coding rate 45 | uint8_t plength = (uint8_t) 8; // preamble length 46 | uint8_t sw = 0x39; // syncword default:0x39 47 | bool cad = false; 48 | bool crc = true; 49 | bool iiq = false; // InvertIQ 50 | }; 51 | 52 | RFM::Settings settings; 53 | RFM::Pins pins; 54 | */ 55 | RFM::Channel channel; 56 | bool active = false; 57 | 58 | virtual ~RFM(); 59 | RFM(Node* parent, const char* name); 60 | void setup(); 61 | void loop(); 62 | //void apply(RFM::Settings* settings); 63 | //int send(Data::Packet* packet); 64 | //void read(RFM::Handler* handler); 65 | 66 | virtual void applySettings(); 67 | virtual void state(CDS::DataBuffer* params, CDS::DataBuffer* response); 68 | virtual void from(CDS::DataBuffer* params); 69 | }; 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/SerialPort/AVRSerialPort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __AVR__ 4 | 5 | uint8_t SerialPort_CONFIG(int index) { 6 | uint8_t config = SERIAL_8N1; 7 | switch(index) { 8 | case 0: { config = SERIAL_5N1; } break; 9 | case 1: { config = SERIAL_6N1; } break; 10 | case 2: { config = SERIAL_7N1; } break; 11 | case 3: { config = SERIAL_8N1; } break; // (the default) 12 | case 4: { config = SERIAL_5N2; } break; 13 | case 5: { config = SERIAL_6N2; } break; 14 | case 6: { config = SERIAL_7N2; } break; 15 | case 7: { config = SERIAL_8N2; } break; 16 | case 8: { config = SERIAL_5E1; } break; // even parity 17 | case 9: { config = SERIAL_6E1; } break; 18 | case 10: { config = SERIAL_7E1; } break; 19 | case 11: { config = SERIAL_8E1; } break; 20 | case 12: { config = SERIAL_5E2; } break; 21 | case 13: { config = SERIAL_6E2; } break; 22 | case 14: { config = SERIAL_7E2; } break; 23 | case 15: { config = SERIAL_8E2; } break; 24 | case 16: { config = SERIAL_5O1; } break; // odd parity 25 | case 17: { config = SERIAL_6O1; } break; 26 | case 18: { config = SERIAL_7O1; } break; 27 | case 19: { config = SERIAL_8O1; } break; 28 | case 20: { config = SERIAL_5O2; } break; 29 | case 21: { config = SERIAL_6O2; } break; 30 | case 22: { config = SERIAL_7O2; } break; 31 | case 23: { config = SERIAL_8O2; } break; 32 | } 33 | return config; 34 | } 35 | 36 | void SerialPort::applySettings() { 37 | CDS::Iterator storage = this->storage(); 38 | 39 | CDS::Iterator rxStorage = CDS::Object::taketo(storage, K("rx")); 40 | CDS::DataBuffer* savedRx = CDS::Element::nextElement(&rxStorage); 41 | uint8_t rx = CDS::Number::value(savedRx); 42 | delete savedRx; 43 | 44 | CDS::Iterator txStorage = CDS::Object::taketo(storage, K("tx")); 45 | CDS::DataBuffer* savedTx = CDS::Element::nextElement(&txStorage); 46 | uint8_t tx = CDS::Number::value(savedTx); 47 | delete savedTx; 48 | 49 | bool hardwareRX = 127 <= rx; 50 | bool hardwareTX = 127 <= tx; 51 | bool softwareRX = 0 <= rx && rx < 127; 52 | bool softwareTX = 0 <= tx && tx < 127; 53 | bool hardware = hardwareRX || hardwareTX; 54 | bool software = softwareRX || softwareTX; 55 | 56 | CDS::Iterator baudrateStorage = CDS::Object::taketo(storage, K("baudrate")); 57 | CDS::DataBuffer* savedBaudrate = CDS::Element::nextElement(&baudrateStorage); 58 | uint32_t baudrate = CDS::Number::value(savedBaudrate); 59 | delete savedBaudrate; 60 | 61 | if (software) { 62 | delete this->swserial; 63 | CDS::Iterator invertStorage = CDS::Object::taketo(storage, K("invert")); 64 | CDS::DataBuffer* savedInvert = CDS::Element::nextElement(&invertStorage); 65 | uint8_t invert = CDS::Number::value(savedInvert); 66 | delete savedInvert; 67 | this->swserial = new SoftwareSerial(rx, tx, invert); 68 | this->swserial->begin(baudrate); 69 | } 70 | 71 | if (hardware) { 72 | CDS::Iterator configStorage = CDS::Object::taketo(storage, K("config")); 73 | CDS::DataBuffer* savedConfig = CDS::Element::nextElement(&configStorage); 74 | uint8_t config = CDS::Number::value(savedConfig); 75 | delete savedConfig; 76 | uint8_t fconfig = SerialPort_CONFIG(config); 77 | Serial.begin(baudrate, fconfig); 78 | while(!Serial); 79 | } 80 | 81 | if (hardwareRX) { 82 | this->input = &Serial; 83 | } else if (softwareRX) { 84 | this->input = this->swserial; 85 | } 86 | 87 | if (hardwareTX) { 88 | this->output = &Serial; 89 | } else if (softwareTX) { 90 | this->output = this->swserial; 91 | } 92 | } 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/SerialPort/Channel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | SerialPort::Channel::Channel(SerialPort* serial) : serial(serial) { 5 | 6 | } 7 | 8 | SerialPort::Channel::~Channel() { 9 | delete this->bytes; 10 | } 11 | 12 | void SerialPort::Channel::loop() { 13 | size_t available = this->serial->available(); 14 | if (available) { 15 | this->lread = millis(); 16 | 17 | if (NULL == this->bytes) this->bytes = new DS::List(); 18 | size_t length = (size_t) this->bytes->length; 19 | this->bytes->resize(length + available); 20 | this->serial->readBytes(this->bytes->buffer + length, available); 21 | yield(); 22 | 23 | CDS::StaticBuffer* staticBuffer = new CDS::StaticBuffer(this->bytes->buffer); 24 | CDS::Iterator* iterator = new CDS::Iterator(staticBuffer, (size_t) this->bytes->length); 25 | bool valid = CDS::Element::valid(iterator); 26 | if (valid) { 27 | iterator->reset(); 28 | CDS::DataBuffer* element = CDS::Element::nextElement(iterator); 29 | for (size_t i = (size_t) 0; i < this->handlers->length; i++) { 30 | DataChannel::Handler* handler = this->handlers->get(i); 31 | handler->onData(this, element); 32 | } 33 | delete element; 34 | delete this->bytes; this->bytes = NULL; 35 | } 36 | delete iterator; 37 | delete staticBuffer; 38 | } else { 39 | uint16_t elapsed = millis() - this->lread; 40 | if (elapsed >= this->iread) { 41 | if (NULL != this->bytes) { 42 | delete this->bytes; this->bytes = NULL; 43 | } 44 | } 45 | } 46 | } 47 | 48 | int SerialPort::Channel::send(CDS::DataBuffer* command) { 49 | int sent = 0; 50 | uint16_t size = CDS::Element::size(command); 51 | //if (0 < size) { 52 | this->serial->flush(); 53 | CDS::StreamBuffer* streamBuffer = new CDS::StreamBuffer(this->serial); 54 | CDS::Iterator* iterator = new CDS::Iterator(streamBuffer, 0); 55 | CDS::Element::serialize(command, iterator); 56 | sent = iterator->index; 57 | delete iterator; 58 | delete streamBuffer; 59 | yield(); 60 | //} 61 | return sent; 62 | } 63 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/SerialPort/ESPSerialPort.cpp: -------------------------------------------------------------------------------- 1 | #ifdef ESP8266 2 | 3 | #include 4 | 5 | SoftwareSerialConfig SerialPort_SWCONFIG(int index) { 6 | SoftwareSerialConfig swconfig = SWSERIAL_8N1; 7 | switch(index) { 8 | case 0: { swconfig = SWSERIAL_5N1; } break; 9 | case 1: { swconfig = SWSERIAL_6N1; } break; 10 | case 2: { swconfig = SWSERIAL_7N1; } break; 11 | case 3: { swconfig = SWSERIAL_8N1; } break; // (the default) 12 | case 4: { swconfig = SWSERIAL_5N2; } break; 13 | case 5: { swconfig = SWSERIAL_6N2; } break; 14 | case 6: { swconfig = SWSERIAL_7N2; } break; 15 | case 7: { swconfig = SWSERIAL_8N2; } break; 16 | case 8: { swconfig = SWSERIAL_5E1; } break; // even parity 17 | case 9: { swconfig = SWSERIAL_6E1; } break; 18 | case 10: { swconfig = SWSERIAL_7E1; } break; 19 | case 11: { swconfig = SWSERIAL_8E1; } break; 20 | case 12: { swconfig = SWSERIAL_5E2; } break; 21 | case 13: { swconfig = SWSERIAL_6E2; } break; 22 | case 14: { swconfig = SWSERIAL_7E2; } break; 23 | case 15: { swconfig = SWSERIAL_8E2; } break; 24 | case 16: { swconfig = SWSERIAL_5O1; } break; // odd parity 25 | case 17: { swconfig = SWSERIAL_6O1; } break; 26 | case 18: { swconfig = SWSERIAL_7O1; } break; 27 | case 19: { swconfig = SWSERIAL_8O1; } break; 28 | case 20: { swconfig = SWSERIAL_5O2; } break; 29 | case 21: { swconfig = SWSERIAL_6O2; } break; 30 | case 22: { swconfig = SWSERIAL_7O2; } break; 31 | case 23: { swconfig = SWSERIAL_8O2; } break; 32 | } 33 | return swconfig; 34 | } 35 | 36 | SerialConfig SerialPort_CONFIG(int index) { 37 | SerialConfig config = SERIAL_8N1; 38 | switch(index) { 39 | case 0: { config = SERIAL_5N1; } break; 40 | case 1: { config = SERIAL_6N1; } break; 41 | case 2: { config = SERIAL_7N1; } break; 42 | case 3: { config = SERIAL_8N1; } break; // (the default) 43 | case 4: { config = SERIAL_5N2; } break; 44 | case 5: { config = SERIAL_6N2; } break; 45 | case 6: { config = SERIAL_7N2; } break; 46 | case 7: { config = SERIAL_8N2; } break; 47 | case 8: { config = SERIAL_5E1; } break; // even parity 48 | case 9: { config = SERIAL_6E1; } break; 49 | case 10: { config = SERIAL_7E1; } break; 50 | case 11: { config = SERIAL_8E1; } break; 51 | case 12: { config = SERIAL_5E2; } break; 52 | case 13: { config = SERIAL_6E2; } break; 53 | case 14: { config = SERIAL_7E2; } break; 54 | case 15: { config = SERIAL_8E2; } break; 55 | case 16: { config = SERIAL_5O1; } break; // odd parity 56 | case 17: { config = SERIAL_6O1; } break; 57 | case 18: { config = SERIAL_7O1; } break; 58 | case 19: { config = SERIAL_8O1; } break; 59 | case 20: { config = SERIAL_5O2; } break; 60 | case 21: { config = SERIAL_6O2; } break; 61 | case 22: { config = SERIAL_7O2; } break; 62 | case 23: { config = SERIAL_8O2; } break; 63 | } 64 | return config; 65 | } 66 | 67 | SerialMode SerialPort_MODE(int tx, int rx) { 68 | SerialMode mode = SERIAL_FULL; 69 | if (0 <= tx && 0 <= rx) { 70 | mode = SERIAL_FULL; 71 | } else { 72 | mode = (0 <= tx) ? SERIAL_TX_ONLY : SERIAL_RX_ONLY; 73 | } 74 | return mode; 75 | } 76 | 77 | 78 | void SerialPort::applySettings() { 79 | CDS::Iterator storage = this->storage(); 80 | 81 | CDS::Iterator rxStorage = CDS::Object::taketo(storage, K("rx")); 82 | CDS::DataBuffer* savedRx = CDS::Element::nextElement(&rxStorage); 83 | uint8_t rx = CDS::Number::value(savedRx); 84 | delete savedRx; 85 | 86 | CDS::Iterator txStorage = CDS::Object::taketo(storage, K("tx")); 87 | CDS::DataBuffer* savedTx = CDS::Element::nextElement(&txStorage); 88 | uint8_t tx = CDS::Number::value(savedTx); 89 | delete savedTx; 90 | 91 | bool hardwareRX = 127 <= rx; 92 | bool hardwareTX = 127 <= tx; 93 | bool softwareRX = 0 <= rx && rx < 127; 94 | bool softwareTX = 0 <= tx && tx < 127; 95 | bool hardware = hardwareRX || hardwareTX; 96 | bool software = softwareRX || softwareTX; 97 | 98 | CDS::Iterator baudrateStorage = CDS::Object::taketo(storage, K("baudrate")); 99 | CDS::DataBuffer* savedBaudrate = CDS::Element::nextElement(&baudrateStorage); 100 | uint32_t baudrate = CDS::Number::value(savedBaudrate); 101 | delete savedBaudrate; 102 | 103 | CDS::Iterator configStorage = CDS::Object::taketo(storage, K("config")); 104 | CDS::DataBuffer* savedConfig = CDS::Element::nextElement(&configStorage); 105 | uint8_t config = CDS::Number::value(savedConfig); 106 | delete savedConfig; 107 | 108 | CDS::Iterator invertStorage = CDS::Object::taketo(storage, K("invert")); 109 | CDS::DataBuffer* savedInvert = CDS::Element::nextElement(&invertStorage); 110 | uint8_t invert = CDS::Number::value(savedInvert); 111 | delete savedInvert; 112 | 113 | CDS::Iterator bsizeStorage = CDS::Object::taketo(storage, K("bsize")); 114 | CDS::DataBuffer* savedBsize = CDS::Element::nextElement(&bsizeStorage); 115 | uint8_t bsize = CDS::Number::value(savedBsize); 116 | delete savedBsize; 117 | 118 | if (software) { 119 | delete this->swserial; 120 | this->swserial = new SoftwareSerial(); 121 | this->swserial->begin( 122 | baudrate, 123 | SerialPort_SWCONFIG(config), 124 | softwareRX ? rx : -1, 125 | softwareTX ? tx : -1, 126 | invert, 127 | bsize); 128 | } 129 | 130 | if (hardware) { 131 | SerialConfig config = SerialPort_CONFIG(config); 132 | SerialMode mode = SerialPort_MODE(rx, tx); 133 | Serial.begin(baudrate, config, mode, 1, invert); 134 | Serial.setRxBufferSize(bsize); 135 | } 136 | 137 | if (hardwareRX) { 138 | this->input = &Serial; 139 | } else if (softwareRX) { 140 | this->input = this->swserial; 141 | } 142 | 143 | if (hardwareTX) { 144 | this->output = &Serial; 145 | } else if (softwareTX) { 146 | this->output = this->swserial; 147 | } 148 | } 149 | 150 | #endif 151 | 152 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/SerialPort/SerialPort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | SerialPort::SerialPort(Node* parent, const char* name) : channel(this), Node(parent, name) { 5 | 6 | } 7 | 8 | SerialPort::~SerialPort() { 9 | 10 | } 11 | 12 | void SerialPort::setup() { 13 | this->applySettings(); 14 | } 15 | 16 | void SerialPort::loop() { 17 | this->channel.loop(); 18 | } 19 | 20 | void SerialPort::save(CDS::DataBuffer* params, CDS::DataBuffer* response) { 21 | Node::save(params, response); 22 | delay(500); // give the other device the chance to reconfigure itself 23 | } 24 | 25 | void SerialPort::state(CDS::DataBuffer* params, CDS::DataBuffer* response) { 26 | CDS::DataBuffer* object = this->rootIT(response); 27 | CDS::DataBuffer* state = CDS::Object::newObject(object, K("state")); 28 | 29 | CDS::Iterator storage = this->storage(); 30 | 31 | CDS::Iterator rxStorage = CDS::Object::taketo(storage, K("rx")); 32 | CDS::DataBuffer* savedRx = CDS::Element::nextElement(&rxStorage); 33 | uint8_t rx = CDS::Number::value(savedRx); 34 | delete savedRx; 35 | 36 | CDS::Iterator txStorage = CDS::Object::taketo(storage, K("tx")); 37 | CDS::DataBuffer* savedTx = CDS::Element::nextElement(&txStorage); 38 | uint8_t tx = CDS::Number::value(savedTx); 39 | delete savedTx; 40 | 41 | bool hardwareRX = 127 <= rx; 42 | bool hardwareTX = 127 <= tx; 43 | bool softwareRX = 0 <= rx && rx < 127; 44 | bool softwareTX = 0 <= tx && tx < 127; 45 | bool hardware = hardwareRX || hardwareTX; 46 | bool software = softwareRX || softwareTX; 47 | bool status = (hardware && !!Serial || (software && !!(*this->swserial))); 48 | CDS::DataBuffer* statusElement = CDS::Object::newNumber(state, K("status")); 49 | CDS::Number::set(statusElement, status); 50 | 51 | CDS::DataBuffer* config = CDS::Element::nextElement(&storage); 52 | CDS::Object::set(state, K("config"), config); 53 | } 54 | 55 | void SerialPort::from(CDS::DataBuffer* params) { 56 | CDS::Iterator storage = this->storage(); 57 | CDS::Element::fill(storage, params); 58 | } 59 | 60 | size_t SerialPort::write(uint8_t b) { 61 | return this->output->write(b); 62 | } 63 | 64 | size_t SerialPort::write(const uint8_t* buffer, size_t size) { 65 | size_t written = this->output->write(buffer, size); 66 | this->flush(); 67 | return written; 68 | } 69 | 70 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/SerialPort/SerialPort.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #ifndef __SerialPort__ 7 | #define __SerialPort__ 8 | 9 | class SerialPort : public Node, public Stream { 10 | public: 11 | 12 | class Channel : public DataChannel { 13 | public: 14 | SerialPort* serial = NULL; 15 | DS::List* bytes = NULL; 16 | uint32_t lread = 0l; 17 | uint16_t iread = 2000u; 18 | 19 | Channel(SerialPort* serial); 20 | ~Channel(); 21 | virtual void loop(); 22 | virtual int send(CDS::DataBuffer* command); 23 | }; 24 | 25 | SoftwareSerial* swserial = NULL; 26 | Stream* input = NULL; 27 | Stream* output = NULL; 28 | Channel channel; 29 | 30 | SerialPort(Node* parent, const char* name); 31 | virtual ~SerialPort(); 32 | void setup(); 33 | void loop(); 34 | 35 | virtual void applySettings(); 36 | virtual void state(CDS::DataBuffer* params, CDS::DataBuffer* response); 37 | virtual void save(CDS::DataBuffer* params, CDS::DataBuffer* response); 38 | virtual void from(CDS::DataBuffer* params); 39 | 40 | virtual int available() {return this->input->available();} 41 | virtual int read() {return this->input->read();} 42 | virtual size_t write(uint8_t b); 43 | virtual size_t write(const uint8_t* buffer, size_t size); 44 | virtual int peek() {return this->input->peek();} 45 | virtual void flush() {this->output->flush();} 46 | // TODO:: add more virtual methods 47 | }; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Sandeep Mistry 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/README.md: -------------------------------------------------------------------------------- 1 | # Arduino LoRa 2 | 3 | [![Build Status](https://travis-ci.org/sandeepmistry/arduino-LoRa.svg?branch=master)](https://travis-ci.org/sandeepmistry/arduino-LoRa) 4 | 5 | An [Arduino](https://arduino.cc/) library for sending and receiving data using [LoRa](https://www.lora-alliance.org/) radios. 6 | 7 | ## Compatible Hardware 8 | 9 | * [Semtech SX1276/77/78/79](http://www.semtech.com/apps/product.php?pn=SX1276) based boards including: 10 | * [Dragino Lora Shield](http://www.dragino.com/products/module/item/102-lora-shield.html) 11 | * [HopeRF](http://www.hoperf.com/rf_transceiver/lora/) [RFM95W](http://www.hoperf.com/rf_transceiver/lora/RFM95W.html), [RFM96W](http://www.hoperf.com/rf_transceiver/lora/RFM96W.html), and [RFM98W](http://www.hoperf.com/rf_transceiver/lora/RFM98W.html) 12 | * [Modtronix](http://modtronix.com/) [inAir4](http://modtronix.com/inair4.html), [inAir9](http://modtronix.com/inair9.html), and [inAir9B](http://modtronix.com/inair9b.html) 13 | * [Arduino MKR WAN 1300](https://store.arduino.cc/usa/mkr-wan-1300) 14 | * **NOTE:** Requires firmware v1.1.6 or later on the on-board Murata module. Please use the [MKRWANFWUpdate_standalone example](https://github.com/arduino-libraries/MKRWAN/blob/master/examples/MKRWANFWUpdate_standalone/MKRWANFWUpdate_standalone.ino) from latest [MKRWAN library](https://github.com/arduino-libraries/MKRWAN) release to update the firmware. 15 | * **WARNING**: [LoRa.onReceive(...)](https://github.com/sandeepmistry/arduino-LoRa/blob/master/API.md#register-callback) and [LoRa.recieve()](https://github.com/sandeepmistry/arduino-LoRa/blob/master/API.md#receive-mode) is not compatible with this board! 16 | 17 | ### Semtech SX1276/77/78/79 wiring 18 | 19 | | Semtech SX1276/77/78/79 | Arduino | 20 | | :---------------------: | :------:| 21 | | VCC | 3.3V | 22 | | GND | GND | 23 | | SCK | SCK | 24 | | MISO | MISO | 25 | | MOSI | MOSI | 26 | | NSS | 10 | 27 | | NRESET | 9 | 28 | | DIO0 | 2 | 29 | 30 | 31 | `NSS`, `NRESET`, and `DIO0` pins can be changed by using `LoRa.setPins(ss, reset, dio0)`. `DIO0` pin is optional, it is only needed for receive callback mode. If `DIO0` pin is used, it **must** be interrupt capable via [`attachInterrupt(...)`](https://www.arduino.cc/en/Reference/AttachInterrupt). 32 | 33 | **NOTES**: 34 | * Some boards (like the Arduino Nano), cannot supply enough current for the SX127x in TX mode. This will cause lockups when sending, be sure to use an external 3.3V supply that can provide at least 120mA's when using these boards. 35 | * If your Arduino board operates at 5V, like the Arduino Uno, Leonardo or Mega, you will need to use a level converter for the wiring to the Semtech SX127x module. Most Semtech SX127x breakout boards do not have logic level converters built-in. 36 | 37 | ## Installation 38 | 39 | ### Using the Arduino IDE Library Manager 40 | 41 | 1. Choose `Sketch` -> `Include Library` -> `Manage Libraries...` 42 | 2. Type `LoRa` into the search box. 43 | 3. Click the row to select the library. 44 | 4. Click the `Install` button to install the library. 45 | 46 | ### Using Git 47 | 48 | ```sh 49 | cd ~/Documents/Arduino/libraries/ 50 | git clone https://github.com/sandeepmistry/arduino-LoRa LoRa 51 | ``` 52 | 53 | ## API 54 | 55 | See [API.md](API.md). 56 | 57 | ## Examples 58 | 59 | See [examples](examples) folder. 60 | 61 | ## FAQ 62 | 63 | **1) Initilizating the LoRa radio is failing** 64 | 65 | Please check the wiring you are using matches what's listed in [Semtech SX1276/77/78/79 wiring](#semtech-sx1276777879-wiring). You can also use `LoRa.setPins(ss, reset, dio0)` to change the default pins used. Some logic level converters cannot operate at 8 MHz, you can call `LoRa.setSPIFrequency(frequency)` to lower the SPI frequency used by the library. Both API's must be called before `LoRa.begin(...)`. 66 | 67 | **2) Can other radios see the packets I'm sending?** 68 | 69 | Yes, any LoRa radio that are configured with the same radio parameters and in range can see the packets you send. 70 | 71 | **3) Is the data I'm sending encrypted?** 72 | 73 | No, all data is sent unencrypted. If want your packet data to be encrypted, you must encrypt it before passing it into this library, followed by decrypting on the receiving end. 74 | 75 | **4) How does this library differ from LoRaWAN libraries?** 76 | 77 | This library exposes the LoRa radio directly, and allows you to send data to any radios in range with same radio parameters. All data is broadcasted and there is no addressing. LoRaWAN builds on top of LoRA, but adds addressing, encryption, and additional layers. It also requires a LoRaWAN gateway and LoRaWAN network and application server. 78 | 79 | **5) Does this library honor duty cycles?** 80 | 81 | No, you have to manage it by your self. 82 | 83 | **6) Which frequencies can I use?** 84 | 85 | You can use [this table](https://www.thethingsnetwork.org/wiki/LoRaWAN/Frequencies/By-Country) to lookup the available frequencies by your country. The selectable frequency also depends on your hardware. You can lookup the data sheet or ask your supplier. 86 | 87 | Please also notice the frequency dependent duty cycles for legal reasons! 88 | 89 | ## License 90 | 91 | This libary is [licensed](LICENSE) under the [MIT Licence](https://en.wikipedia.org/wiki/MIT_License). 92 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/examples/LoRaDumpRegisters/LoRaDumpRegisters.ino: -------------------------------------------------------------------------------- 1 | /* 2 | LoRa register dump 3 | 4 | This examples shows how to inspect and output the LoRa radio's 5 | registers on the Serial interface 6 | */ 7 | #include // include libraries 8 | #include 9 | 10 | void setup() { 11 | Serial.begin(9600); // initialize serial 12 | while (!Serial); 13 | 14 | Serial.println("LoRa Dump Registers"); 15 | 16 | // override the default CS, reset, and IRQ pins (optional) 17 | // LoRa.setPins(7, 6, 1); // set CS, reset, IRQ pin 18 | 19 | if (!LoRa.begin(915E6)) { // initialize ratio at 915 MHz 20 | Serial.println("LoRa init failed. Check your connections."); 21 | while (true); // if failed, do nothing 22 | } 23 | 24 | LoRa.dumpRegisters(Serial); 25 | } 26 | 27 | 28 | void loop() { 29 | } 30 | 31 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/examples/LoRaDuplex/LoRaDuplex.ino: -------------------------------------------------------------------------------- 1 | /* 2 | LoRa Duplex communication 3 | 4 | Sends a message every half second, and polls continually 5 | for new incoming messages. Implements a one-byte addressing scheme, 6 | with 0xFF as the broadcast address. 7 | 8 | Uses readString() from Stream class to read payload. The Stream class' 9 | timeout may affect other functuons, like the radio's callback. For an 10 | 11 | created 28 April 2017 12 | by Tom Igoe 13 | */ 14 | #include // include libraries 15 | #include 16 | 17 | const int csPin = 7; // LoRa radio chip select 18 | const int resetPin = 6; // LoRa radio reset 19 | const int irqPin = 1; // change for your board; must be a hardware interrupt pin 20 | 21 | String outgoing; // outgoing message 22 | 23 | byte msgCount = 0; // count of outgoing messages 24 | byte localAddress = 0xBB; // address of this device 25 | byte destination = 0xFF; // destination to send to 26 | long lastSendTime = 0; // last send time 27 | int interval = 2000; // interval between sends 28 | 29 | void setup() { 30 | Serial.begin(9600); // initialize serial 31 | while (!Serial); 32 | 33 | Serial.println("LoRa Duplex"); 34 | 35 | // override the default CS, reset, and IRQ pins (optional) 36 | LoRa.setPins(csPin, resetPin, irqPin);// set CS, reset, IRQ pin 37 | 38 | if (!LoRa.begin(915E6)) { // initialize ratio at 915 MHz 39 | Serial.println("LoRa init failed. Check your connections."); 40 | while (true); // if failed, do nothing 41 | } 42 | 43 | Serial.println("LoRa init succeeded."); 44 | } 45 | 46 | void loop() { 47 | if (millis() - lastSendTime > interval) { 48 | String message = "HeLoRa World!"; // send a message 49 | sendMessage(message); 50 | Serial.println("Sending " + message); 51 | lastSendTime = millis(); // timestamp the message 52 | interval = random(2000) + 1000; // 2-3 seconds 53 | } 54 | 55 | // parse for a packet, and call onReceive with the result: 56 | onReceive(LoRa.parsePacket()); 57 | } 58 | 59 | void sendMessage(String outgoing) { 60 | LoRa.beginPacket(); // start packet 61 | LoRa.write(destination); // add destination address 62 | LoRa.write(localAddress); // add sender address 63 | LoRa.write(msgCount); // add message ID 64 | LoRa.write(outgoing.length()); // add payload length 65 | LoRa.print(outgoing); // add payload 66 | LoRa.endPacket(); // finish packet and send it 67 | msgCount++; // increment message ID 68 | } 69 | 70 | void onReceive(int packetSize) { 71 | if (packetSize == 0) return; // if there's no packet, return 72 | 73 | // read packet header bytes: 74 | int recipient = LoRa.read(); // recipient address 75 | byte sender = LoRa.read(); // sender address 76 | byte incomingMsgId = LoRa.read(); // incoming msg ID 77 | byte incomingLength = LoRa.read(); // incoming msg length 78 | 79 | String incoming = ""; 80 | 81 | while (LoRa.available()) { 82 | incoming += (char)LoRa.read(); 83 | } 84 | 85 | if (incomingLength != incoming.length()) { // check length for error 86 | Serial.println("error: message length does not match length"); 87 | return; // skip rest of function 88 | } 89 | 90 | // if the recipient isn't this device or broadcast, 91 | if (recipient != localAddress && recipient != 0xFF) { 92 | Serial.println("This message is not for me."); 93 | return; // skip rest of function 94 | } 95 | 96 | // if message is for this device, or broadcast, print details: 97 | Serial.println("Received from: 0x" + String(sender, HEX)); 98 | Serial.println("Sent to: 0x" + String(recipient, HEX)); 99 | Serial.println("Message ID: " + String(incomingMsgId)); 100 | Serial.println("Message length: " + String(incomingLength)); 101 | Serial.println("Message: " + incoming); 102 | Serial.println("RSSI: " + String(LoRa.packetRssi())); 103 | Serial.println("Snr: " + String(LoRa.packetSnr())); 104 | Serial.println(); 105 | } 106 | 107 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/examples/LoRaDuplexCallback/LoRaDuplexCallback.ino: -------------------------------------------------------------------------------- 1 | /* 2 | LoRa Duplex communication wth callback 3 | 4 | Sends a message every half second, and uses callback 5 | for new incoming messages. Implements a one-byte addressing scheme, 6 | with 0xFF as the broadcast address. 7 | 8 | Note: while sending, LoRa radio is not listening for incoming messages. 9 | Note2: when using the callback method, you can't use any of the Stream 10 | functions that rely on the timeout, such as readString, parseInt(), etc. 11 | 12 | created 28 April 2017 13 | by Tom Igoe 14 | */ 15 | #include // include libraries 16 | #include 17 | 18 | #ifdef ARDUINO_SAMD_MKRWAN1300 19 | #error "This example is not compatible with the Arduino MKR WAN 1300 board!" 20 | #endif 21 | 22 | const int csPin = 7; // LoRa radio chip select 23 | const int resetPin = 6; // LoRa radio reset 24 | const int irqPin = 1; // change for your board; must be a hardware interrupt pin 25 | 26 | String outgoing; // outgoing message 27 | byte msgCount = 0; // count of outgoing messages 28 | byte localAddress = 0xBB; // address of this device 29 | byte destination = 0xFF; // destination to send to 30 | long lastSendTime = 0; // last send time 31 | int interval = 2000; // interval between sends 32 | 33 | void setup() { 34 | Serial.begin(9600); // initialize serial 35 | while (!Serial); 36 | 37 | Serial.println("LoRa Duplex with callback"); 38 | 39 | // override the default CS, reset, and IRQ pins (optional) 40 | LoRa.setPins(csPin, resetPin, irqPin);// set CS, reset, IRQ pin 41 | 42 | if (!LoRa.begin(915E6)) { // initialize ratio at 915 MHz 43 | Serial.println("LoRa init failed. Check your connections."); 44 | while (true); // if failed, do nothing 45 | } 46 | 47 | LoRa.onReceive(onReceive); 48 | LoRa.receive(); 49 | Serial.println("LoRa init succeeded."); 50 | } 51 | 52 | void loop() { 53 | if (millis() - lastSendTime > interval) { 54 | String message = "HeLoRa World!"; // send a message 55 | sendMessage(message); 56 | Serial.println("Sending " + message); 57 | lastSendTime = millis(); // timestamp the message 58 | interval = random(2000) + 1000; // 2-3 seconds 59 | LoRa.receive(); // go back into receive mode 60 | } 61 | } 62 | 63 | void sendMessage(String outgoing) { 64 | LoRa.beginPacket(); // start packet 65 | LoRa.write(destination); // add destination address 66 | LoRa.write(localAddress); // add sender address 67 | LoRa.write(msgCount); // add message ID 68 | LoRa.write(outgoing.length()); // add payload length 69 | LoRa.print(outgoing); // add payload 70 | LoRa.endPacket(); // finish packet and send it 71 | msgCount++; // increment message ID 72 | } 73 | 74 | void onReceive(int packetSize) { 75 | if (packetSize == 0) return; // if there's no packet, return 76 | 77 | // read packet header bytes: 78 | int recipient = LoRa.read(); // recipient address 79 | byte sender = LoRa.read(); // sender address 80 | byte incomingMsgId = LoRa.read(); // incoming msg ID 81 | byte incomingLength = LoRa.read(); // incoming msg length 82 | 83 | String incoming = ""; // payload of packet 84 | 85 | while (LoRa.available()) { // can't use readString() in callback, so 86 | incoming += (char)LoRa.read(); // add bytes one by one 87 | } 88 | 89 | if (incomingLength != incoming.length()) { // check length for error 90 | Serial.println("error: message length does not match length"); 91 | return; // skip rest of function 92 | } 93 | 94 | // if the recipient isn't this device or broadcast, 95 | if (recipient != localAddress && recipient != 0xFF) { 96 | Serial.println("This message is not for me."); 97 | return; // skip rest of function 98 | } 99 | 100 | // if message is for this device, or broadcast, print details: 101 | Serial.println("Received from: 0x" + String(sender, HEX)); 102 | Serial.println("Sent to: 0x" + String(recipient, HEX)); 103 | Serial.println("Message ID: " + String(incomingMsgId)); 104 | Serial.println("Message length: " + String(incomingLength)); 105 | Serial.println("Message: " + incoming); 106 | Serial.println("RSSI: " + String(LoRa.packetRssi())); 107 | Serial.println("Snr: " + String(LoRa.packetSnr())); 108 | Serial.println(); 109 | } 110 | 111 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/examples/LoRaReceiver/LoRaReceiver.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void setup() { 5 | Serial.begin(9600); 6 | while (!Serial); 7 | 8 | Serial.println("LoRa Receiver"); 9 | 10 | if (!LoRa.begin(915E6)) { 11 | Serial.println("Starting LoRa failed!"); 12 | while (1); 13 | } 14 | } 15 | 16 | void loop() { 17 | // try to parse packet 18 | int packetSize = LoRa.parsePacket(); 19 | if (packetSize) { 20 | // received a packet 21 | Serial.print("Received packet '"); 22 | 23 | // read packet 24 | while (LoRa.available()) { 25 | Serial.print((char)LoRa.read()); 26 | } 27 | 28 | // print RSSI of packet 29 | Serial.print("' with RSSI "); 30 | Serial.println(LoRa.packetRssi()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/examples/LoRaReceiverCallback/LoRaReceiverCallback.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef ARDUINO_SAMD_MKRWAN1300 5 | #error "This example is not compatible with the Arduino MKR WAN 1300 board!" 6 | #endif 7 | 8 | void setup() { 9 | Serial.begin(9600); 10 | while (!Serial); 11 | 12 | Serial.println("LoRa Receiver Callback"); 13 | 14 | if (!LoRa.begin(915E6)) { 15 | Serial.println("Starting LoRa failed!"); 16 | while (1); 17 | } 18 | 19 | // register the receive callback 20 | LoRa.onReceive(onReceive); 21 | 22 | // put the radio into receive mode 23 | LoRa.receive(); 24 | } 25 | 26 | void loop() { 27 | // do nothing 28 | } 29 | 30 | void onReceive(int packetSize) { 31 | // received a packet 32 | Serial.print("Received packet '"); 33 | 34 | // read packet 35 | for (int i = 0; i < packetSize; i++) { 36 | Serial.print((char)LoRa.read()); 37 | } 38 | 39 | // print RSSI of packet 40 | Serial.print("' with RSSI "); 41 | Serial.println(LoRa.packetRssi()); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/examples/LoRaSender/LoRaSender.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int counter = 0; 5 | 6 | void setup() { 7 | Serial.begin(9600); 8 | while (!Serial); 9 | 10 | Serial.println("LoRa Sender"); 11 | 12 | if (!LoRa.begin(915E6)) { 13 | Serial.println("Starting LoRa failed!"); 14 | while (1); 15 | } 16 | } 17 | 18 | void loop() { 19 | Serial.print("Sending packet: "); 20 | Serial.println(counter); 21 | 22 | // send packet 23 | LoRa.beginPacket(); 24 | LoRa.print("hello "); 25 | LoRa.print(counter); 26 | LoRa.endPacket(); 27 | 28 | counter++; 29 | 30 | delay(5000); 31 | } 32 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/examples/LoRaSenderNonBlocking/LoRaSenderNonBlocking.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int counter = 0; 5 | 6 | void setup() { 7 | Serial.begin(9600); 8 | while (!Serial); 9 | 10 | Serial.println("LoRa Sender non-blocking"); 11 | 12 | if (!LoRa.begin(915E6)) { 13 | Serial.println("Starting LoRa failed!"); 14 | while (1); 15 | } 16 | } 17 | 18 | void loop() { 19 | // wait until the radio is ready to send a packet 20 | while (LoRa.beginPacket() == 0) { 21 | Serial.print("waiting for radio ... "); 22 | delay(100); 23 | } 24 | 25 | Serial.print("Sending packet non-blocking: "); 26 | Serial.println(counter); 27 | 28 | // send in async / non-blocking mode 29 | LoRa.beginPacket(); 30 | LoRa.print("hello "); 31 | LoRa.print(counter); 32 | LoRa.endPacket(true); // true = async / non-blocking mode 33 | 34 | counter++; 35 | } 36 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/examples/LoRaSenderNonBlockingCallback/LoRaSenderNonBlockingCallback.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int counter = 0; 5 | 6 | void setup() { 7 | Serial.begin(9600); 8 | while (!Serial); 9 | 10 | Serial.println("LoRa Sender non-blocking Callback"); 11 | 12 | if (!LoRa.begin(915E6)) { 13 | Serial.println("Starting LoRa failed!"); 14 | while (1); 15 | } 16 | 17 | LoRa.onTxDone(onTxDone); 18 | } 19 | 20 | void loop() { 21 | if (runEvery(5000)) { // repeat every 5000 millis 22 | 23 | Serial.print("Sending packet non-blocking: "); 24 | Serial.println(counter); 25 | 26 | // send in async / non-blocking mode 27 | LoRa.beginPacket(); 28 | LoRa.print("hello "); 29 | LoRa.print(counter); 30 | LoRa.endPacket(true); // true = async / non-blocking mode 31 | 32 | counter++; 33 | } 34 | } 35 | 36 | void onTxDone() { 37 | Serial.println("TxDone"); 38 | } 39 | 40 | boolean runEvery(unsigned long interval) 41 | { 42 | static unsigned long previousMillis = 0; 43 | unsigned long currentMillis = millis(); 44 | if (currentMillis - previousMillis >= interval) 45 | { 46 | previousMillis = currentMillis; 47 | return true; 48 | } 49 | return false; 50 | } 51 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/examples/LoRaSetSpread/LoRaSetSpread.ino: -------------------------------------------------------------------------------- 1 | /* 2 | LoRa Duplex communication with Spreading Factor 3 | 4 | Sends a message every half second, and polls continually 5 | for new incoming messages. Sets the LoRa radio's spreading factor. 6 | 7 | Spreading factor affects how far apart the radio's transmissions 8 | are, across the available bandwidth. Radios with different spreading 9 | factors will not receive each other's transmissions. This is one way you 10 | can filter out radios you want to ignore, without making an addressing scheme. 11 | 12 | Spreading factor affects reliability of transmission at high rates, however, 13 | so avoid a hugh spreading factor when you're sending continually. 14 | 15 | See the Semtech datasheet, http://www.semtech.com/images/datasheet/sx1276.pdf 16 | for more on Spreading Factor. 17 | 18 | created 28 April 2017 19 | by Tom Igoe 20 | */ 21 | #include // include libraries 22 | #include 23 | 24 | const int csPin = 7; // LoRa radio chip select 25 | const int resetPin = 6; // LoRa radio reset 26 | const int irqPin = 1; // change for your board; must be a hardware interrupt pin 27 | 28 | byte msgCount = 0; // count of outgoing messages 29 | int interval = 2000; // interval between sends 30 | long lastSendTime = 0; // time of last packet send 31 | 32 | void setup() { 33 | Serial.begin(9600); // initialize serial 34 | while (!Serial); 35 | 36 | Serial.println("LoRa Duplex - Set spreading factor"); 37 | 38 | // override the default CS, reset, and IRQ pins (optional) 39 | LoRa.setPins(csPin, resetPin, irqPin); // set CS, reset, IRQ pin 40 | 41 | if (!LoRa.begin(915E6)) { // initialize ratio at 915 MHz 42 | Serial.println("LoRa init failed. Check your connections."); 43 | while (true); // if failed, do nothing 44 | } 45 | 46 | LoRa.setSpreadingFactor(8); // ranges from 6-12,default 7 see API docs 47 | Serial.println("LoRa init succeeded."); 48 | } 49 | 50 | void loop() { 51 | if (millis() - lastSendTime > interval) { 52 | String message = "HeLoRa World! "; // send a message 53 | message += msgCount; 54 | sendMessage(message); 55 | Serial.println("Sending " + message); 56 | lastSendTime = millis(); // timestamp the message 57 | interval = random(2000) + 1000; // 2-3 seconds 58 | msgCount++; 59 | } 60 | 61 | // parse for a packet, and call onReceive with the result: 62 | onReceive(LoRa.parsePacket()); 63 | } 64 | 65 | void sendMessage(String outgoing) { 66 | LoRa.beginPacket(); // start packet 67 | LoRa.print(outgoing); // add payload 68 | LoRa.endPacket(); // finish packet and send it 69 | msgCount++; // increment message ID 70 | } 71 | 72 | void onReceive(int packetSize) { 73 | if (packetSize == 0) return; // if there's no packet, return 74 | 75 | // read packet header bytes: 76 | String incoming = ""; 77 | 78 | while (LoRa.available()) { 79 | incoming += (char)LoRa.read(); 80 | } 81 | 82 | Serial.println("Message: " + incoming); 83 | Serial.println("RSSI: " + String(LoRa.packetRssi())); 84 | Serial.println("Snr: " + String(LoRa.packetSnr())); 85 | Serial.println(); 86 | } 87 | 88 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/examples/LoRaSetSyncWord/LoRaSetSyncWord.ino: -------------------------------------------------------------------------------- 1 | /* 2 | LoRa Duplex communication with Sync Word 3 | 4 | Sends a message every half second, and polls continually 5 | for new incoming messages. Sets the LoRa radio's Sync Word. 6 | 7 | Spreading factor is basically the radio's network ID. Radios with different 8 | Sync Words will not receive each other's transmissions. This is one way you 9 | can filter out radios you want to ignore, without making an addressing scheme. 10 | 11 | See the Semtech datasheet, http://www.semtech.com/images/datasheet/sx1276.pdf 12 | for more on Sync Word. 13 | 14 | created 28 April 2017 15 | by Tom Igoe 16 | */ 17 | #include // include libraries 18 | #include 19 | const int csPin = 7; // LoRa radio chip select 20 | const int resetPin = 6; // LoRa radio reset 21 | const int irqPin = 1; // change for your board; must be a hardware interrupt pin 22 | 23 | byte msgCount = 0; // count of outgoing messages 24 | int interval = 2000; // interval between sends 25 | long lastSendTime = 0; // time of last packet send 26 | 27 | void setup() { 28 | Serial.begin(9600); // initialize serial 29 | while (!Serial); 30 | 31 | Serial.println("LoRa Duplex - Set sync word"); 32 | 33 | // override the default CS, reset, and IRQ pins (optional) 34 | LoRa.setPins(csPin, resetPin, irqPin);// set CS, reset, IRQ pin 35 | 36 | if (!LoRa.begin(915E6)) { // initialize ratio at 915 MHz 37 | Serial.println("LoRa init failed. Check your connections."); 38 | while (true); // if failed, do nothing 39 | } 40 | 41 | LoRa.setSyncWord(0xF3); // ranges from 0-0xFF, default 0x34, see API docs 42 | Serial.println("LoRa init succeeded."); 43 | } 44 | 45 | void loop() { 46 | if (millis() - lastSendTime > interval) { 47 | String message = "HeLoRa World! "; // send a message 48 | message += msgCount; 49 | sendMessage(message); 50 | Serial.println("Sending " + message); 51 | lastSendTime = millis(); // timestamp the message 52 | interval = random(2000) + 1000; // 2-3 seconds 53 | msgCount++; 54 | } 55 | 56 | // parse for a packet, and call onReceive with the result: 57 | onReceive(LoRa.parsePacket()); 58 | } 59 | 60 | void sendMessage(String outgoing) { 61 | LoRa.beginPacket(); // start packet 62 | LoRa.print(outgoing); // add payload 63 | LoRa.endPacket(); // finish packet and send it 64 | msgCount++; // increment message ID 65 | } 66 | 67 | void onReceive(int packetSize) { 68 | if (packetSize == 0) return; // if there's no packet, return 69 | 70 | // read packet header bytes: 71 | String incoming = ""; 72 | 73 | while (LoRa.available()) { 74 | incoming += (char)LoRa.read(); 75 | } 76 | 77 | Serial.println("Message: " + incoming); 78 | Serial.println("RSSI: " + String(LoRa.packetRssi())); 79 | Serial.println("Snr: " + String(LoRa.packetSnr())); 80 | Serial.println(); 81 | } 82 | 83 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/examples/LoRaSimpleGateway/LoRaSimpleGateway.ino: -------------------------------------------------------------------------------- 1 | /* 2 | LoRa Simple Gateway/Node Exemple 3 | 4 | This code uses InvertIQ function to create a simple Gateway/Node logic. 5 | 6 | Gateway - Sends messages with enableInvertIQ() 7 | - Receives messages with disableInvertIQ() 8 | 9 | Node - Sends messages with disableInvertIQ() 10 | - Receives messages with enableInvertIQ() 11 | 12 | With this arrangement a Gateway never receive messages from another Gateway 13 | and a Node never receive message from another Node. 14 | Only Gateway to Node and vice versa. 15 | 16 | This code receives messages and sends a message every second. 17 | 18 | InvertIQ function basically invert the LoRa I and Q signals. 19 | 20 | See the Semtech datasheet, http://www.semtech.com/images/datasheet/sx1276.pdf 21 | for more on InvertIQ register 0x33. 22 | 23 | created 05 August 2018 24 | by Luiz H. Cassettari 25 | */ 26 | 27 | #include // include libraries 28 | #include 29 | 30 | const long frequency = 915E6; // LoRa Frequency 31 | 32 | const int csPin = 10; // LoRa radio chip select 33 | const int resetPin = 9; // LoRa radio reset 34 | const int irqPin = 2; // change for your board; must be a hardware interrupt pin 35 | 36 | void setup() { 37 | Serial.begin(9600); // initialize serial 38 | while (!Serial); 39 | 40 | LoRa.setPins(csPin, resetPin, irqPin); 41 | 42 | if (!LoRa.begin(frequency)) { 43 | Serial.println("LoRa init failed. Check your connections."); 44 | while (true); // if failed, do nothing 45 | } 46 | 47 | Serial.println("LoRa init succeeded."); 48 | Serial.println(); 49 | Serial.println("LoRa Simple Gateway"); 50 | Serial.println("Only receive messages from nodes"); 51 | Serial.println("Tx: invertIQ enable"); 52 | Serial.println("Rx: invertIQ disable"); 53 | Serial.println(); 54 | 55 | LoRa.onReceive(onReceive); 56 | LoRa.onTxDone(onTxDone); 57 | LoRa_rxMode(); 58 | } 59 | 60 | void loop() { 61 | if (runEvery(5000)) { // repeat every 5000 millis 62 | 63 | String message = "HeLoRa World! "; 64 | message += "I'm a Gateway! "; 65 | message += millis(); 66 | 67 | LoRa_sendMessage(message); // send a message 68 | 69 | Serial.println("Send Message!"); 70 | } 71 | } 72 | 73 | void LoRa_rxMode(){ 74 | LoRa.disableInvertIQ(); // normal mode 75 | LoRa.receive(); // set receive mode 76 | } 77 | 78 | void LoRa_txMode(){ 79 | LoRa.idle(); // set standby mode 80 | LoRa.enableInvertIQ(); // active invert I and Q signals 81 | } 82 | 83 | void LoRa_sendMessage(String message) { 84 | LoRa_txMode(); // set tx mode 85 | LoRa.beginPacket(); // start packet 86 | LoRa.print(message); // add payload 87 | LoRa.endPacket(true); // finish packet and send it 88 | } 89 | 90 | void onReceive(int packetSize) { 91 | String message = ""; 92 | 93 | while (LoRa.available()) { 94 | message += (char)LoRa.read(); 95 | } 96 | 97 | Serial.print("Gateway Receive: "); 98 | Serial.println(message); 99 | } 100 | 101 | void onTxDone() { 102 | Serial.println("TxDone"); 103 | LoRa_rxMode(); 104 | } 105 | 106 | boolean runEvery(unsigned long interval) 107 | { 108 | static unsigned long previousMillis = 0; 109 | unsigned long currentMillis = millis(); 110 | if (currentMillis - previousMillis >= interval) 111 | { 112 | previousMillis = currentMillis; 113 | return true; 114 | } 115 | return false; 116 | } 117 | 118 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/examples/LoRaSimpleNode/LoRaSimpleNode.ino: -------------------------------------------------------------------------------- 1 | /* 2 | LoRa Simple Gateway/Node Exemple 3 | 4 | This code uses InvertIQ function to create a simple Gateway/Node logic. 5 | 6 | Gateway - Sends messages with enableInvertIQ() 7 | - Receives messages with disableInvertIQ() 8 | 9 | Node - Sends messages with disableInvertIQ() 10 | - Receives messages with enableInvertIQ() 11 | 12 | With this arrangement a Gateway never receive messages from another Gateway 13 | and a Node never receive message from another Node. 14 | Only Gateway to Node and vice versa. 15 | 16 | This code receives messages and sends a message every second. 17 | 18 | InvertIQ function basically invert the LoRa I and Q signals. 19 | 20 | See the Semtech datasheet, http://www.semtech.com/images/datasheet/sx1276.pdf 21 | for more on InvertIQ register 0x33. 22 | 23 | created 05 August 2018 24 | by Luiz H. Cassettari 25 | */ 26 | 27 | #include // include libraries 28 | #include 29 | 30 | const long frequency = 915E6; // LoRa Frequency 31 | 32 | const int csPin = 10; // LoRa radio chip select 33 | const int resetPin = 9; // LoRa radio reset 34 | const int irqPin = 2; // change for your board; must be a hardware interrupt pin 35 | 36 | void setup() { 37 | Serial.begin(9600); // initialize serial 38 | while (!Serial); 39 | 40 | LoRa.setPins(csPin, resetPin, irqPin); 41 | 42 | if (!LoRa.begin(frequency)) { 43 | Serial.println("LoRa init failed. Check your connections."); 44 | while (true); // if failed, do nothing 45 | } 46 | 47 | Serial.println("LoRa init succeeded."); 48 | Serial.println(); 49 | Serial.println("LoRa Simple Node"); 50 | Serial.println("Only receive messages from gateways"); 51 | Serial.println("Tx: invertIQ disable"); 52 | Serial.println("Rx: invertIQ enable"); 53 | Serial.println(); 54 | 55 | LoRa.onReceive(onReceive); 56 | LoRa.onTxDone(onTxDone); 57 | LoRa_rxMode(); 58 | } 59 | 60 | void loop() { 61 | if (runEvery(1000)) { // repeat every 1000 millis 62 | 63 | String message = "HeLoRa World! "; 64 | message += "I'm a Node! "; 65 | message += millis(); 66 | 67 | LoRa_sendMessage(message); // send a message 68 | 69 | Serial.println("Send Message!"); 70 | } 71 | } 72 | 73 | void LoRa_rxMode(){ 74 | LoRa.enableInvertIQ(); // active invert I and Q signals 75 | LoRa.receive(); // set receive mode 76 | } 77 | 78 | void LoRa_txMode(){ 79 | LoRa.idle(); // set standby mode 80 | LoRa.disableInvertIQ(); // normal mode 81 | } 82 | 83 | void LoRa_sendMessage(String message) { 84 | LoRa_txMode(); // set tx mode 85 | LoRa.beginPacket(); // start packet 86 | LoRa.print(message); // add payload 87 | LoRa.endPacket(true); // finish packet and send it 88 | } 89 | 90 | void onReceive(int packetSize) { 91 | String message = ""; 92 | 93 | while (LoRa.available()) { 94 | message += (char)LoRa.read(); 95 | } 96 | 97 | Serial.print("Node Receive: "); 98 | Serial.println(message); 99 | } 100 | 101 | void onTxDone() { 102 | Serial.println("TxDone"); 103 | LoRa_rxMode(); 104 | } 105 | 106 | boolean runEvery(unsigned long interval) 107 | { 108 | static unsigned long previousMillis = 0; 109 | unsigned long currentMillis = millis(); 110 | if (currentMillis - previousMillis >= interval) 111 | { 112 | previousMillis = currentMillis; 113 | return true; 114 | } 115 | return false; 116 | } 117 | 118 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/issue_template.md: -------------------------------------------------------------------------------- 1 | Are you receiving `Starting LoRa failed` while using the demo code? 2 | 3 | PLEASE see the [FAQ #1](https://github.com/sandeepmistry/arduino-LoRa#faq) about using [setPins](https://github.com/sandeepmistry/arduino-LoRa/blob/master/API.md#set-pins) **BEFORE** submitting an issue. 4 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For LoRa 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | LoRa KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | begin KEYWORD2 16 | end KEYWORD2 17 | 18 | beginPacket KEYWORD2 19 | endPacket KEYWORD2 20 | 21 | parsePacket KEYWORD2 22 | packetRssi KEYWORD2 23 | packetSnr KEYWORD2 24 | packetFrequencyError KEYWORD2 25 | 26 | write KEYWORD2 27 | 28 | available KEYWORD2 29 | read KEYWORD2 30 | peek KEYWORD2 31 | flush KEYWORD2 32 | 33 | onReceive KEYWORD2 34 | onTxDone KEYWORD2 35 | receive KEYWORD2 36 | idle KEYWORD2 37 | sleep KEYWORD2 38 | 39 | setTxPower KEYWORD2 40 | setFrequency KEYWORD2 41 | setSpreadingFactor KEYWORD2 42 | setSignalBandwidth KEYWORD2 43 | setCodingRate4 KEYWORD2 44 | setPreambleLength KEYWORD2 45 | setSyncWord KEYWORD2 46 | enableCrc KEYWORD2 47 | disableCrc KEYWORD2 48 | enableInvertIQ KEYWORD2 49 | disableInvertIQ KEYWORD2 50 | 51 | random KEYWORD2 52 | setPins KEYWORD2 53 | setSPIFrequency KEYWORD2 54 | dumpRegisters KEYWORD2 55 | 56 | ####################################### 57 | # Constants (LITERAL1) 58 | ####################################### 59 | 60 | PA_OUTPUT_RFO_PIN LITERAL1 61 | PA_OUTPUT_PA_BOOST_PIN LITERAL1 62 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/library.properties: -------------------------------------------------------------------------------- 1 | name=LoRa 2 | version=0.7.2 3 | author=Sandeep Mistry 4 | maintainer=Sandeep Mistry 5 | sentence=An Arduino library for sending and receiving data using LoRa radios. 6 | paragraph=Supports Semtech SX1276/77/78/79 based boards/shields. 7 | category=Communication 8 | url=https://github.com/sandeepmistry/arduino-LoRa 9 | architectures=* 10 | includes=LoRa.h 11 | -------------------------------------------------------------------------------- /ArduinoIDE/USBRFMApp/libraries/arduino-LoRa-master/src/LoRa.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Sandeep Mistry. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #ifndef LORA_H 5 | #define LORA_H 6 | 7 | #include 8 | #include 9 | 10 | #if defined(ARDUINO_SAMD_MKRWAN1300) 11 | #define LORA_DEFAULT_SPI SPI1 12 | #define LORA_DEFAULT_SPI_FREQUENCY 200000 13 | #define LORA_DEFAULT_SS_PIN LORA_IRQ_DUMB 14 | #define LORA_DEFAULT_RESET_PIN -1 15 | #define LORA_DEFAULT_DIO0_PIN -1 16 | #elif defined(ARDUINO_SAMD_MKRWAN1310) 17 | #define LORA_DEFAULT_SPI SPI1 18 | #define LORA_DEFAULT_SPI_FREQUENCY 200000 19 | #define LORA_DEFAULT_SS_PIN LORA_IRQ_DUMB 20 | #define LORA_DEFAULT_RESET_PIN -1 21 | #define LORA_DEFAULT_DIO0_PIN LORA_IRQ 22 | #else 23 | #define LORA_DEFAULT_SPI SPI 24 | #define LORA_DEFAULT_SPI_FREQUENCY 8E6 25 | #define LORA_DEFAULT_SS_PIN 10 26 | #define LORA_DEFAULT_RESET_PIN 9 27 | #define LORA_DEFAULT_DIO0_PIN 2 28 | #endif 29 | 30 | #define PA_OUTPUT_RFO_PIN 0 31 | #define PA_OUTPUT_PA_BOOST_PIN 1 32 | 33 | class LoRaClass : public Stream { 34 | public: 35 | LoRaClass(); 36 | 37 | int begin(long frequency); 38 | void end(); 39 | 40 | int beginPacket(int implicitHeader = false); 41 | int endPacket(bool async = false); 42 | 43 | int parsePacket(int size = 0); 44 | int packetRssi(); 45 | float packetSnr(); 46 | long packetFrequencyError(); 47 | 48 | // from Print 49 | virtual size_t write(uint8_t byte); 50 | virtual size_t write(const uint8_t *buffer, size_t size); 51 | 52 | // from Stream 53 | virtual int available(); 54 | virtual int read(); 55 | virtual int peek(); 56 | virtual void flush(); 57 | 58 | #ifndef ARDUINO_SAMD_MKRWAN1300 59 | void onReceive(void(*callback)(int)); 60 | void onTxDone(void(*callback)()); 61 | 62 | void receive(int size = 0); 63 | #endif 64 | void idle(); 65 | void sleep(); 66 | 67 | void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN); 68 | void setFrequency(long frequency); 69 | void setSpreadingFactor(int sf); 70 | void setSignalBandwidth(long sbw); 71 | void setCodingRate4(int denominator); 72 | void setPreambleLength(long length); 73 | void setSyncWord(int sw); 74 | void enableCrc(); 75 | void disableCrc(); 76 | void enableInvertIQ(); 77 | void disableInvertIQ(); 78 | 79 | void setOCP(uint8_t mA); // Over Current Protection control 80 | 81 | // deprecated 82 | void crc() { enableCrc(); } 83 | void noCrc() { disableCrc(); } 84 | 85 | byte random(); 86 | 87 | void setPins(int ss = LORA_DEFAULT_SS_PIN, int reset = LORA_DEFAULT_RESET_PIN, int dio0 = LORA_DEFAULT_DIO0_PIN); 88 | void setSPI(SPIClass& spi); 89 | void setSPIFrequency(uint32_t frequency); 90 | 91 | void dumpRegisters(Stream& out); 92 | 93 | private: 94 | void explicitHeaderMode(); 95 | void implicitHeaderMode(); 96 | 97 | void handleDio0Rise(); 98 | bool isTransmitting(); 99 | 100 | int getSpreadingFactor(); 101 | long getSignalBandwidth(); 102 | 103 | void setLdoFlag(); 104 | 105 | uint8_t readRegister(uint8_t address); 106 | void writeRegister(uint8_t address, uint8_t value); 107 | uint8_t singleTransfer(uint8_t address, uint8_t value); 108 | 109 | static void onDio0Rise(); 110 | 111 | private: 112 | SPISettings _spiSettings; 113 | SPIClass* _spi; 114 | int _ss; 115 | int _reset; 116 | int _dio0; 117 | long _frequency; 118 | int _packetIndex; 119 | int _implicitHeaderMode; 120 | void (*_onReceive)(int); 121 | void (*_onTxDone)(); 122 | }; 123 | 124 | extern LoRaClass LoRa; 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # USB RFM App 2 | smartphone LoRa device connection - Android - USB - Arduino - LoRa 3 | 4 | Instructions on how to make it work can be found here https://www.hackster.io/pulsartronic/smartphone-lora-connection-diy-bde258 5 | Google Play Store: https://play.google.com/store/apps/details?id=com.pulsartronic.usbrfmapp 6 | 7 | # Contribute 8 | An open source project is a forever Work In Progress. Feel free to be constructive. 9 | 10 | Default configuration is in: 11 | ```sh 12 | ArduinoIDE/USBRFMApp/USBRFMApp/Defaults.h 13 | ``` 14 | You should change it before uploading it to your board, based on your hardware, though you can later change it through the web interface. 15 | Values are in hexadecimal, i bet you can handle them. 16 | The data structure is a compact object/array/binary model, i should write documentation for it and i will, the module where it is handled is called CDS, 17 | which stands for Compact Data Structure. 18 | ```sh 19 | ArduinoIDE/USBRFMApp/libraries/CDS 20 | ``` 21 | The main goal is to work with a balance between 22 | 1) binary data 23 | 2) object data model, based in JSON 24 | 3) and limited RAM 25 | 26 | 27 | 28 | # TODO 29 | There are many todo's, one example is: CAD (Channel Activity Detection) is not supported yet, if you want 30 | to implement it, it would be fantastic, if you don't know how, you can open an issue asking for implementation 31 | in the following repo: https://github.com/sandeepmistry/arduino-LoRa 32 | 33 | 34 | 35 | # Credits 36 | An Arduino library for sending and receiving data using LoRa radios. 37 | https://github.com/sandeepmistry/arduino-LoRa 38 | 39 | Usb serial controller for Android 40 | https://github.com/felHR85/UsbSerial 41 | -------------------------------------------------------------------------------- /USBRFMApp.v1.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulsartronic/USBRFMApp/9eab4a93bd7d080595ae13ea22a16d37dc5213c1/USBRFMApp.v1.apk --------------------------------------------------------------------------------