├── 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 |
6 |
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 |
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 |
--------------------------------------------------------------------------------
/AndroidStudio/USBRFMApp/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AndroidStudio/USBRFMApp/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
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 |
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 | [](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
--------------------------------------------------------------------------------