├── Artik-nodes-sample
├── artik-adc-nodes
│ ├── artik-adc-nodes-flow-on-artik.json
│ └── artik-adc-nodes-flow-on-fred.json
├── artik-in-nodes
│ ├── artik-in-nodes-flow-on-artik.json
│ └── artik-in-nodes-flow-on-fred.json
├── artik-out-nodes
│ ├── artik-out-nodes-flow-on-artik.json
│ └── artik-out-nodes-flow-on-fred.json
└── artik-pwm-nodes
│ ├── artik-pwm-nodes-flow-on-artik.json
│ └── artik-pwm-nodes-flow-on-fred.json
├── HTML-chat-app
├── advance-chat-app.json
└── basic-chat-app-sample-flow.json
├── README.md
├── SQLite-litedb-node
└── litedb-tutorial.json
├── arduino-mqtt
├── arduino_mqtt_sample.ino
│ └── arduino_mqtt_sample.ino.ino
└── sample-flow-on-fred.json
├── chatbot-with-watson
├── chatbot-sample-flow
└── watson-conversation-sample-sensetecnic.json
├── connecting-device-to-cloud
├── receive-from-cloud-via-rjlTest2.json
├── talk-to-device-on-rjlTest.json
└── talk-to-server-on-rjlTest.json
├── multitech-lorawan-gateway-fred
├── FRED-receiver-and-forward-to-telegram.json
├── gateway-node-red.json
├── generate-map.json
└── map-screen-shot.png
├── node-red-contrib-dashboard
└── node-red-contrib-dashboard-sample.json
├── opc-ua-sample-flow
├── OPC Painting Demo.opf
├── flow-on-fred.json
└── flow-on-windows.json
├── osisoft-web-api-node
└── osisoft-web-api-node.json
├── post-data-to-dweetio-using-fred
└── post-data-to-dweetio-using-fred.json
├── ttn-feather-m0
├── feather-m0-ttn-abp-works-with-multitech-with-sensors
│ └── feather-m0-ttn-abp-works-with-multitech-with-sensors.ino
└── libraries
│ ├── Adafruit_Unified_Sensor
│ ├── Adafruit_Sensor.h
│ ├── README.md
│ └── library.properties
│ ├── DHT-sensor-library
│ ├── .github
│ │ ├── ISSUE_TEMPLATE.md
│ │ └── PULL_REQUEST_TEMPLATE.md
│ ├── DHT.cpp
│ ├── DHT.h
│ ├── DHT_U.cpp
│ ├── DHT_U.h
│ ├── README.md
│ ├── examples
│ │ ├── DHT_Unified_Sensor
│ │ │ └── DHT_Unified_Sensor.ino
│ │ └── DHTtester
│ │ │ └── DHTtester.ino
│ ├── keywords.txt
│ └── library.properties
│ ├── arduino-lmic-master
│ ├── README.md
│ ├── doc
│ │ ├── LMiC-v1.5.pdf
│ │ ├── README.txt
│ │ └── release-notes.txt
│ ├── examples
│ │ ├── raw
│ │ │ └── raw.ino
│ │ ├── ttn-abp
│ │ │ └── ttn-abp.ino
│ │ └── ttn-otaa
│ │ │ └── ttn-otaa.ino
│ ├── library.properties
│ └── src
│ │ ├── hal
│ │ ├── hal.cpp
│ │ └── hal.h
│ │ ├── lmic.h
│ │ └── lmic
│ │ ├── aes.c
│ │ ├── config.h
│ │ ├── hal.h
│ │ ├── lmic.c
│ │ ├── lmic.h
│ │ ├── lorabase.h
│ │ ├── oslmic.c
│ │ ├── oslmic.h
│ │ └── radio.c
│ └── elapsedMillis
│ ├── .travis.yml
│ ├── LICENSE
│ ├── README.md
│ ├── elapsedMillis.h
│ ├── examples
│ ├── GettingStarted
│ │ └── GettingStarted.ino
│ ├── timeouts
│ │ └── timeouts.ino
│ └── timingComparison
│ │ └── timingComparison.ino
│ ├── keywords.txt
│ ├── library.json
│ └── library.properties
└── watson-cognitive-servies
└── twitter-tone-analyzer.json
/Artik-nodes-sample/artik-adc-nodes/artik-adc-nodes-flow-on-artik.json:
--------------------------------------------------------------------------------
1 | [{"id":"c5af3ed4.84781","type":"fred out","z":"1115fb04.52cbf5","name":"","server":"","client":"32c29980.ffc156","x":479,"y":380,"wires":[]},{"id":"6fee83ca.81f93c","type":"fred in","z":"1115fb04.52cbf5","name":"","server":"","client":"6117533e.0a7bbc","x":150,"y":63,"wires":[["958edbe.d948728"]]},{"id":"958edbe.d948728","type":"json","z":"1115fb04.52cbf5","name":"","x":165,"y":142,"wires":[["27b87524.e29c9a"]]},{"id":"27b87524.e29c9a","type":"artik_adc","z":"1115fb04.52cbf5","name":"","pin":"0","platform":"artik_10","x":248,"y":228,"wires":[["bac35dc.69cd3a"]]},{"id":"bac35dc.69cd3a","type":"function","z":"1115fb04.52cbf5","name":"delete session","func":"delete msg._session;\nreturn msg;","outputs":1,"noerr":0,"x":352,"y":313,"wires":[["c5af3ed4.84781"]]},{"id":"32c29980.ffc156","type":"fred-client","z":"1115fb04.52cbf5","endpoint":"artikADCReceive","private":false,"username":"demotutorial","wholemsg":"false"},{"id":"6117533e.0a7bbc","type":"fred-client","z":"1115fb04.52cbf5","endpoint":"artikADCSend","private":false,"username":"demotutorial","wholemsg":"false"}]
--------------------------------------------------------------------------------
/Artik-nodes-sample/artik-adc-nodes/artik-adc-nodes-flow-on-fred.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "65943886.2a7fa8",
4 | "type": "inject",
5 | "z": "7ea2f961.7447b8",
6 | "name": "",
7 | "topic": "",
8 | "payload": "",
9 | "payloadType": "date",
10 | "repeat": "",
11 | "crontab": "",
12 | "once": false,
13 | "x": 140,
14 | "y": 114,
15 | "wires": [
16 | [
17 | "2b682d49.ed9462"
18 | ]
19 | ]
20 | },
21 | {
22 | "id": "2b682d49.ed9462",
23 | "type": "fred out",
24 | "z": "7ea2f961.7447b8",
25 | "name": "",
26 | "server": "1795a272.f0faee",
27 | "client": "",
28 | "x": 392,
29 | "y": 114,
30 | "wires": []
31 | },
32 | {
33 | "id": "b8bc56d8.b36958",
34 | "type": "fred in",
35 | "z": "7ea2f961.7447b8",
36 | "name": "",
37 | "server": "38439352.849a0c",
38 | "client": "",
39 | "x": 157,
40 | "y": 190,
41 | "wires": [
42 | [
43 | "f9284830.12c608"
44 | ]
45 | ]
46 | },
47 | {
48 | "id": "f9284830.12c608",
49 | "type": "json",
50 | "z": "7ea2f961.7447b8",
51 | "name": "",
52 | "x": 311,
53 | "y": 257,
54 | "wires": [
55 | [
56 | "c65c0afc.e29588",
57 | "184d3ff6.e3d7"
58 | ]
59 | ]
60 | },
61 | {
62 | "id": "c65c0afc.e29588",
63 | "type": "debug",
64 | "z": "7ea2f961.7447b8",
65 | "name": "",
66 | "active": true,
67 | "console": "false",
68 | "complete": "false",
69 | "x": 455,
70 | "y": 317,
71 | "wires": []
72 | },
73 | {
74 | "id": "184d3ff6.e3d7",
75 | "type": "ui_chart",
76 | "z": "7ea2f961.7447b8",
77 | "tab": "a1b7478f.1b3038",
78 | "name": "",
79 | "group": "",
80 | "order": 1,
81 | "interpolate": "linear",
82 | "nodata": "No Data",
83 | "removeOlder": 1,
84 | "removeOlderUnit": "86400",
85 | "x": 443,
86 | "y": 371,
87 | "wires": [
88 | [],
89 | []
90 | ]
91 | },
92 | {
93 | "id": "1795a272.f0faee",
94 | "type": "fred-server",
95 | "z": "7ea2f961.7447b8",
96 | "endpoint": "artikADCSend",
97 | "private": false,
98 | "wholemsg": "false"
99 | },
100 | {
101 | "id": "38439352.849a0c",
102 | "type": "fred-server",
103 | "z": "7ea2f961.7447b8",
104 | "endpoint": "artikADCReceive",
105 | "private": false,
106 | "wholemsg": "false"
107 | },
108 | {
109 | "id": "a1b7478f.1b3038",
110 | "type": "ui_tab",
111 | "z": "7ea2f961.7447b8",
112 | "name": "Home",
113 | "icon": "dashboard",
114 | "order": "1"
115 | }
116 | ]
--------------------------------------------------------------------------------
/Artik-nodes-sample/artik-in-nodes/artik-in-nodes-flow-on-artik.json:
--------------------------------------------------------------------------------
1 | [{"id":"389827c2.7caf58","type":"fred in","z":"8a1aa086.977d","name":"","server":"","client":"413262dc.e5d8fc","x":195,"y":304,"wires":[["5468ace6.e51ce4"]]},{"id":"5468ace6.e51ce4","type":"json","z":"8a1aa086.977d","name":"","x":267,"y":372,"wires":[["eeefd39e.e6d93"]]},{"id":"eeefd39e.e6d93","type":"artik_in","z":"8a1aa086.977d","name":"","pin":"pin12","platform":"10","enableInterrupt":true,"edge":"both","debounce":"200","x":316,"y":440,"wires":[["a2135803.796ec8"]]},{"id":"a2135803.796ec8","type":"function","z":"8a1aa086.977d","name":"delete session","func":"delete msg._session;\nreturn msg;","outputs":1,"noerr":0,"x":403,"y":496,"wires":[["165c50be.a9d22f"]]},{"id":"165c50be.a9d22f","type":"fred out","z":"8a1aa086.977d","name":"","server":"","client":"58cdcb80.051604","x":535,"y":552,"wires":[]},{"id":"413262dc.e5d8fc","type":"fred-client","z":"8a1aa086.977d","endpoint":"artikInSend","private":false,"username":"demotutorial","wholemsg":"false"},{"id":"58cdcb80.051604","type":"fred-client","z":"8a1aa086.977d","endpoint":"artikInReceive","private":false,"username":"demotutorial","wholemsg":"false"}]
--------------------------------------------------------------------------------
/Artik-nodes-sample/artik-in-nodes/artik-in-nodes-flow-on-fred.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "65943886.2a7fa8",
4 | "type": "inject",
5 | "z": "7ea2f961.7447b8",
6 | "name": "",
7 | "topic": "",
8 | "payload": "",
9 | "payloadType": "date",
10 | "repeat": "",
11 | "crontab": "",
12 | "once": false,
13 | "x": 140,
14 | "y": 114,
15 | "wires": [
16 | [
17 | "2b682d49.ed9462"
18 | ]
19 | ]
20 | },
21 | {
22 | "id": "2b682d49.ed9462",
23 | "type": "fred out",
24 | "z": "7ea2f961.7447b8",
25 | "name": "",
26 | "server": "b439c00d.fc7b1",
27 | "client": "",
28 | "x": 382,
29 | "y": 114,
30 | "wires": []
31 | },
32 | {
33 | "id": "b8bc56d8.b36958",
34 | "type": "fred in",
35 | "z": "7ea2f961.7447b8",
36 | "name": "",
37 | "server": "d00907c.36b12f8",
38 | "client": "",
39 | "x": 147,
40 | "y": 190,
41 | "wires": [
42 | [
43 | "f9284830.12c608"
44 | ]
45 | ]
46 | },
47 | {
48 | "id": "f9284830.12c608",
49 | "type": "json",
50 | "z": "7ea2f961.7447b8",
51 | "name": "",
52 | "x": 301,
53 | "y": 264,
54 | "wires": [
55 | [
56 | "c65c0afc.e29588"
57 | ]
58 | ]
59 | },
60 | {
61 | "id": "c65c0afc.e29588",
62 | "type": "debug",
63 | "z": "7ea2f961.7447b8",
64 | "name": "",
65 | "active": true,
66 | "console": "false",
67 | "complete": "false",
68 | "x": 455,
69 | "y": 317,
70 | "wires": []
71 | },
72 | {
73 | "id": "b439c00d.fc7b1",
74 | "type": "fred-server",
75 | "z": "7ea2f961.7447b8",
76 | "endpoint": "artikInSend",
77 | "private": false,
78 | "wholemsg": "false"
79 | },
80 | {
81 | "id": "d00907c.36b12f8",
82 | "type": "fred-server",
83 | "z": "7ea2f961.7447b8",
84 | "endpoint": "artikInReceive",
85 | "private": false,
86 | "wholemsg": "false"
87 | }
88 | ]
--------------------------------------------------------------------------------
/Artik-nodes-sample/artik-out-nodes/artik-out-nodes-flow-on-artik.json:
--------------------------------------------------------------------------------
1 | [{"id":"13cf5601.1952da","type":"fred in","z":"f40098ea.b750d8","name":"","server":"","client":"8791a02e.79394","x":211,"y":393,"wires":[["dc8bf9d9.4360e8"]]},{"id":"dc8bf9d9.4360e8","type":"json","z":"f40098ea.b750d8","name":"","x":280,"y":459,"wires":[["135128a.6758dd7"]]},{"id":"135128a.6758dd7","type":"artik_out","z":"f40098ea.b750d8","name":"","pin":"pin13","platform":"10","state":"0","enableInitialState":true,"initialState":"1","x":372,"y":516,"wires":[]},{"id":"8791a02e.79394","type":"fred-client","z":"f40098ea.b750d8","endpoint":"artikOut","private":false,"username":"demotutorial","wholemsg":"false"}]
--------------------------------------------------------------------------------
/Artik-nodes-sample/artik-out-nodes/artik-out-nodes-flow-on-fred.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "d303cf0f.46371",
4 | "type": "inject",
5 | "z": "7ea2f961.7447b8",
6 | "name": "",
7 | "topic": "",
8 | "payload": "",
9 | "payloadType": "date",
10 | "repeat": "",
11 | "crontab": "",
12 | "once": false,
13 | "x": 118,
14 | "y": 82,
15 | "wires": [
16 | [
17 | "2847a02d.b2e09"
18 | ]
19 | ]
20 | },
21 | {
22 | "id": "cf1b9106.10263",
23 | "type": "inject",
24 | "z": "7ea2f961.7447b8",
25 | "name": "",
26 | "topic": "",
27 | "payload": "",
28 | "payloadType": "date",
29 | "repeat": "",
30 | "crontab": "",
31 | "once": false,
32 | "x": 115,
33 | "y": 145,
34 | "wires": [
35 | [
36 | "e64e6142.12a86"
37 | ]
38 | ]
39 | },
40 | {
41 | "id": "2847a02d.b2e09",
42 | "type": "function",
43 | "z": "7ea2f961.7447b8",
44 | "name": "HIGH",
45 | "func": "msg.payload = {\n state:1\n}\nreturn msg;",
46 | "outputs": 1,
47 | "noerr": 0,
48 | "x": 276,
49 | "y": 84,
50 | "wires": [
51 | [
52 | "ba1265f2.33e788"
53 | ]
54 | ]
55 | },
56 | {
57 | "id": "e64e6142.12a86",
58 | "type": "function",
59 | "z": "7ea2f961.7447b8",
60 | "name": "LOW",
61 | "func": "msg.payload = {\n state:0\n}\nreturn msg;",
62 | "outputs": 1,
63 | "noerr": 0,
64 | "x": 277,
65 | "y": 142,
66 | "wires": [
67 | [
68 | "ba1265f2.33e788"
69 | ]
70 | ]
71 | },
72 | {
73 | "id": "ba1265f2.33e788",
74 | "type": "fred out",
75 | "z": "7ea2f961.7447b8",
76 | "name": "",
77 | "server": "5a020af7.4d4e74",
78 | "client": "",
79 | "x": 512,
80 | "y": 113,
81 | "wires": []
82 | },
83 | {
84 | "id": "5a020af7.4d4e74",
85 | "type": "fred-server",
86 | "z": "7ea2f961.7447b8",
87 | "endpoint": "artikOut",
88 | "private": false,
89 | "wholemsg": "false"
90 | }
91 | ]
--------------------------------------------------------------------------------
/Artik-nodes-sample/artik-pwm-nodes/artik-pwm-nodes-flow-on-artik.json:
--------------------------------------------------------------------------------
1 | [{"id":"8d034a15.658ba8","type":"fred in","z":"835414c2.c79de8","name":"","server":"","client":"98e13231.1278d","x":273,"y":516,"wires":[["90297516.0d3918"]]},{"id":"90297516.0d3918","type":"json","z":"835414c2.c79de8","name":"","x":288,"y":595,"wires":[["2597c02.379774"]]},{"id":"2597c02.379774","type":"artik_pwm","z":"835414c2.c79de8","name":"","pin":"0","dutyCycle":"500000000","period":"1000000000","state":"1","enableInitialState":true,"initialState":"1","initialDutyCycle":"100000000","initialPeriod":"1000000000","x":437,"y":657,"wires":[]},{"id":"98e13231.1278d","type":"fred-client","z":"835414c2.c79de8","endpoint":"artikPWMSend","private":false,"username":"demotutorial","wholemsg":"false"}]
--------------------------------------------------------------------------------
/Artik-nodes-sample/artik-pwm-nodes/artik-pwm-nodes-flow-on-fred.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "9cc4465d.0abda8",
4 | "type": "inject",
5 | "z": "7ea2f961.7447b8",
6 | "name": "",
7 | "topic": "",
8 | "payload": "",
9 | "payloadType": "date",
10 | "repeat": "",
11 | "crontab": "",
12 | "once": false,
13 | "x": 122,
14 | "y": 136,
15 | "wires": [
16 | [
17 | "a7b43672.12b878"
18 | ]
19 | ]
20 | },
21 | {
22 | "id": "600eacae.f6e114",
23 | "type": "inject",
24 | "z": "7ea2f961.7447b8",
25 | "name": "",
26 | "topic": "",
27 | "payload": "",
28 | "payloadType": "date",
29 | "repeat": "",
30 | "crontab": "",
31 | "once": false,
32 | "x": 120,
33 | "y": 199,
34 | "wires": [
35 | [
36 | "1c20a5e4.7bf53a"
37 | ]
38 | ]
39 | },
40 | {
41 | "id": "3fd332fd.dc87ee",
42 | "type": "inject",
43 | "z": "7ea2f961.7447b8",
44 | "name": "",
45 | "topic": "",
46 | "payload": "",
47 | "payloadType": "date",
48 | "repeat": "",
49 | "crontab": "",
50 | "once": false,
51 | "x": 118,
52 | "y": 258,
53 | "wires": [
54 | [
55 | "ac0a7e70.da68a"
56 | ]
57 | ]
58 | },
59 | {
60 | "id": "a7b43672.12b878",
61 | "type": "function",
62 | "z": "7ea2f961.7447b8",
63 | "name": "on",
64 | "func": "var newMsg = {\n payload:{\n state:1,\n period:1000000000,\n dutyCycle:500000000\n }\n}\nreturn newMsg;",
65 | "outputs": 1,
66 | "noerr": 0,
67 | "x": 334,
68 | "y": 165,
69 | "wires": [
70 | [
71 | "e83daab1.c0bac8"
72 | ]
73 | ]
74 | },
75 | {
76 | "id": "1c20a5e4.7bf53a",
77 | "type": "function",
78 | "z": "7ea2f961.7447b8",
79 | "name": "off",
80 | "func": "var newMsg = {\n payload:{\n state:0\n }\n}\nreturn newMsg;",
81 | "outputs": 1,
82 | "noerr": 0,
83 | "x": 334,
84 | "y": 246,
85 | "wires": [
86 | [
87 | "e83daab1.c0bac8"
88 | ]
89 | ]
90 | },
91 | {
92 | "id": "ac0a7e70.da68a",
93 | "type": "function",
94 | "z": "7ea2f961.7447b8",
95 | "name": "otherway",
96 | "func": "var newMsg = {\n payload:{\n state:1,\n period: 1000000000,\n dutyCycle: 1000\n }\n}\nreturn newMsg;",
97 | "outputs": 1,
98 | "noerr": 0,
99 | "x": 354,
100 | "y": 327,
101 | "wires": [
102 | [
103 | "e83daab1.c0bac8"
104 | ]
105 | ]
106 | },
107 | {
108 | "id": "e83daab1.c0bac8",
109 | "type": "fred out",
110 | "z": "7ea2f961.7447b8",
111 | "name": "",
112 | "server": "65bdc91.da27938",
113 | "client": "",
114 | "x": 609,
115 | "y": 247,
116 | "wires": []
117 | },
118 | {
119 | "id": "65bdc91.da27938",
120 | "type": "fred-server",
121 | "z": "7ea2f961.7447b8",
122 | "endpoint": "artikPWMSend",
123 | "private": false,
124 | "wholemsg": "false"
125 | }
126 | ]
--------------------------------------------------------------------------------
/HTML-chat-app/advance-chat-app.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "5ec458f1.138c38",
4 | "type": "websocket in",
5 | "z": "87394a82.590968",
6 | "name": "",
7 | "server": "b7aff9e4.169148",
8 | "client": "",
9 | "x": 144,
10 | "y": 91,
11 | "wires": [
12 | [
13 | "131b8e85.9779d1",
14 | "97364bef.9c82e8"
15 | ]
16 | ]
17 | },
18 | {
19 | "id": "131b8e85.9779d1",
20 | "type": "debug",
21 | "z": "87394a82.590968",
22 | "name": "",
23 | "active": true,
24 | "console": "false",
25 | "complete": "false",
26 | "x": 379,
27 | "y": 61,
28 | "wires": []
29 | },
30 | {
31 | "id": "97364bef.9c82e8",
32 | "type": "json",
33 | "z": "87394a82.590968",
34 | "name": "",
35 | "x": 187,
36 | "y": 160,
37 | "wires": [
38 | [
39 | "9b78abe3.c07f38"
40 | ]
41 | ]
42 | },
43 | {
44 | "id": "9b78abe3.c07f38",
45 | "type": "change",
46 | "z": "87394a82.590968",
47 | "name": "",
48 | "rules": [
49 | {
50 | "t": "set",
51 | "p": "data",
52 | "pt": "msg",
53 | "to": "payload",
54 | "tot": "msg"
55 | },
56 | {
57 | "t": "set",
58 | "p": "payload",
59 | "pt": "msg",
60 | "to": "payload.msg",
61 | "tot": "msg"
62 | }
63 | ],
64 | "action": "",
65 | "property": "",
66 | "from": "",
67 | "to": "",
68 | "reg": false,
69 | "x": 271,
70 | "y": 211,
71 | "wires": [
72 | [
73 | "63d531b4.527cb"
74 | ]
75 | ]
76 | },
77 | {
78 | "id": "63d531b4.527cb",
79 | "type": "sentiment",
80 | "z": "87394a82.590968",
81 | "name": "",
82 | "x": 405,
83 | "y": 265,
84 | "wires": [
85 | [
86 | "a66309be.4927f8"
87 | ]
88 | ]
89 | },
90 | {
91 | "id": "a66309be.4927f8",
92 | "type": "function",
93 | "z": "87394a82.590968",
94 | "name": "",
95 | "func": "return {\n payload: {\n msg:msg.data.msg,\n timestamp:msg.data.timestamp,\n sentiment:msg.sentiment.score\n }\n};",
96 | "outputs": 1,
97 | "noerr": 0,
98 | "x": 497,
99 | "y": 213,
100 | "wires": [
101 | [
102 | "553dfff1.fcc6b",
103 | "5eca304b.486fb"
104 | ]
105 | ]
106 | },
107 | {
108 | "id": "553dfff1.fcc6b",
109 | "type": "websocket out",
110 | "z": "87394a82.590968",
111 | "name": "",
112 | "server": "a3eb30ea.807f8",
113 | "client": "",
114 | "x": 608,
115 | "y": 138,
116 | "wires": []
117 | },
118 | {
119 | "id": "d09ce1bf.a2d58",
120 | "type": "websocket in",
121 | "z": "87394a82.590968",
122 | "name": "",
123 | "server": "67607e72.dda2",
124 | "client": "",
125 | "x": 146,
126 | "y": 395,
127 | "wires": [
128 | [
129 | "f07dfe56.0b79c"
130 | ]
131 | ]
132 | },
133 | {
134 | "id": "f07dfe56.0b79c",
135 | "type": "template",
136 | "z": "87394a82.590968",
137 | "name": "",
138 | "field": "payload",
139 | "fieldType": "msg",
140 | "format": "handlebars",
141 | "syntax": "mustache",
142 | "template": "\n\n
\n \n FRED-powered chat app\n \n \n \n\n\n \n \n \n \n \n\n",
143 | "x": 220,
144 | "y": 471,
145 | "wires": [
146 | [
147 | "2e432626.e511ba"
148 | ]
149 | ]
150 | },
151 | {
152 | "id": "2e432626.e511ba",
153 | "type": "http response",
154 | "z": "87394a82.590968",
155 | "name": "",
156 | "x": 358,
157 | "y": 414,
158 | "wires": []
159 | },
160 | {
161 | "id": "5eca304b.486fb",
162 | "type": "debug",
163 | "z": "87394a82.590968",
164 | "name": "",
165 | "active": true,
166 | "console": "false",
167 | "complete": "false",
168 | "x": 643,
169 | "y": 245,
170 | "wires": []
171 | },
172 | {
173 | "id": "b7aff9e4.169148",
174 | "type": "websocket-listener",
175 | "z": "87394a82.590968",
176 | "path": "/public/messagereceive",
177 | "wholemsg": "false"
178 | },
179 | {
180 | "id": "a3eb30ea.807f8",
181 | "type": "websocket-listener",
182 | "z": "87394a82.590968",
183 | "path": "/public/messagepublish",
184 | "wholemsg": "false"
185 | },
186 | {
187 | "id": "67607e72.dda2",
188 | "type": "websocket-listener",
189 | "z": "87394a82.590968",
190 | "path": "/public/chatroom",
191 | "wholemsg": "false"
192 | }
193 | ]
--------------------------------------------------------------------------------
/HTML-chat-app/basic-chat-app-sample-flow.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "eb923c67.49e73",
4 | "type": "websocket in",
5 | "z": "87394a82.590968",
6 | "name": "",
7 | "server": "b7aff9e4.169148",
8 | "client": "",
9 | "x": 199,
10 | "y": 185,
11 | "wires": [
12 | [
13 | "af42d30e.17711",
14 | "f11873fc.66e48"
15 | ]
16 | ]
17 | },
18 | {
19 | "id": "af42d30e.17711",
20 | "type": "debug",
21 | "z": "87394a82.590968",
22 | "name": "",
23 | "active": true,
24 | "console": "false",
25 | "complete": "false",
26 | "x": 457,
27 | "y": 139,
28 | "wires": []
29 | },
30 | {
31 | "id": "b966d569.b25928",
32 | "type": "http in",
33 | "z": "87394a82.590968",
34 | "name": "",
35 | "url": "/public/chatroom",
36 | "method": "get",
37 | "swaggerDoc": "",
38 | "x": 160,
39 | "y": 337,
40 | "wires": [
41 | [
42 | "e9f38850.4bc358"
43 | ]
44 | ]
45 | },
46 | {
47 | "id": "e9f38850.4bc358",
48 | "type": "template",
49 | "z": "87394a82.590968",
50 | "name": "Chatroom HTML",
51 | "field": "payload",
52 | "fieldType": "msg",
53 | "format": "text",
54 | "syntax": "mustache",
55 | "template": "\n\n\n \n FRED-powered chat app\n \n \n \n\n\n \n \n \n \n \n\n",
56 | "x": 379,
57 | "y": 398,
58 | "wires": [
59 | [
60 | "d48ad141.db2f9"
61 | ]
62 | ]
63 | },
64 | {
65 | "id": "d48ad141.db2f9",
66 | "type": "http response",
67 | "z": "87394a82.590968",
68 | "name": "",
69 | "x": 492,
70 | "y": 343,
71 | "wires": []
72 | },
73 | {
74 | "id": "f11873fc.66e48",
75 | "type": "function",
76 | "z": "87394a82.590968",
77 | "name": "",
78 | "func": "return {payload: JSON.parse(msg.payload)};",
79 | "outputs": 1,
80 | "noerr": 0,
81 | "x": 378,
82 | "y": 259,
83 | "wires": [
84 | [
85 | "df28add7.a73c7"
86 | ]
87 | ]
88 | },
89 | {
90 | "id": "df28add7.a73c7",
91 | "type": "websocket out",
92 | "z": "87394a82.590968",
93 | "name": "",
94 | "server": "a3eb30ea.807f8",
95 | "client": "",
96 | "x": 559,
97 | "y": 207,
98 | "wires": []
99 | },
100 | {
101 | "id": "b7aff9e4.169148",
102 | "type": "websocket-listener",
103 | "z": "87394a82.590968",
104 | "path": "/public/messagereceive",
105 | "wholemsg": "false"
106 | },
107 | {
108 | "id": "a3eb30ea.807f8",
109 | "type": "websocket-listener",
110 | "z": "87394a82.590968",
111 | "path": "/public/messagepublish",
112 | "wholemsg": "false"
113 | }
114 | ]
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FRED(Cloud based Node-RED) sample flows
2 |
3 |
4 | This repository contains sample flows that were demonstrated on the [Sensetecnic developers site](http://developers.sensetecnic.com/). The folder names suggest which tutorials they were linked to.
5 |
6 | To find out more about importing sample flows, please refer to [How to Import a Node-RED Flow](http://developers.sensetecnic.com/article/how-to-import-a-node-red-flow/).
7 |
8 | To find out more about Sense Tecnic, please refer to [Sensetecnic.com](http://sensetecnic.com/)
9 |
10 | To find out more about FRED (Cloud based Node-RED), please refer to [FRED](https://fred.sensetecnic.com/)
11 |
12 | If you have any other questions, please contact us via info@sensetecnic.com
13 |
--------------------------------------------------------------------------------
/SQLite-litedb-node/litedb-tutorial.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "35881632.6e706a",
4 | "type": "litedb",
5 | "z": "e6691547.05bc98",
6 | "name": "",
7 | "x": 490,
8 | "y": 140,
9 | "wires": [
10 | [
11 | "de6e047c.26add8"
12 | ]
13 | ]
14 | },
15 | {
16 | "id": "cfe9844b.ad9ba8",
17 | "type": "inject",
18 | "z": "e6691547.05bc98",
19 | "name": "create database table",
20 | "topic": "CREATE TABLE RANDOMNUM( TIMESTAMP INT PRIMARY KEY NOT NULL, VALUE INT NOT NULL, BOOL INT NOT NULL)",
21 | "payload": "",
22 | "payloadType": "date",
23 | "repeat": "",
24 | "crontab": "",
25 | "once": false,
26 | "x": 140,
27 | "y": 80,
28 | "wires": [
29 | [
30 | "35881632.6e706a"
31 | ]
32 | ]
33 | },
34 | {
35 | "id": "de6e047c.26add8",
36 | "type": "debug",
37 | "z": "e6691547.05bc98",
38 | "name": "",
39 | "active": true,
40 | "console": "false",
41 | "complete": "false",
42 | "x": 680,
43 | "y": 101,
44 | "wires": []
45 | },
46 | {
47 | "id": "d59e6372.41336",
48 | "type": "inject",
49 | "z": "e6691547.05bc98",
50 | "name": "insert data",
51 | "topic": "",
52 | "payload": "",
53 | "payloadType": "date",
54 | "repeat": "10",
55 | "crontab": "",
56 | "once": false,
57 | "x": 130,
58 | "y": 140,
59 | "wires": [
60 | [
61 | "84ae8290.2be1c"
62 | ]
63 | ]
64 | },
65 | {
66 | "id": "84ae8290.2be1c",
67 | "type": "function",
68 | "z": "e6691547.05bc98",
69 | "name": "write query",
70 | "func": "var randomNum = Math.round(Math.random()*100);\nvar largeBool = (randomNum > 50)?1:0;\nvar newMsg = {\n \"topic\": \"INSERT INTO RANDOMNUM VALUES ( \" + msg.payload + \", \" + randomNum + \", \" + largeBool + \")\"\n}\n\nreturn newMsg;",
71 | "outputs": 1,
72 | "noerr": 0,
73 | "x": 310,
74 | "y": 140,
75 | "wires": [
76 | [
77 | "35881632.6e706a"
78 | ]
79 | ]
80 | },
81 | {
82 | "id": "aa467606.c19cd8",
83 | "type": "inject",
84 | "z": "e6691547.05bc98",
85 | "name": "view records",
86 | "topic": "SELECT * FROM RANDOMNUM ORDER BY TIMESTAMP DESC LIMIT 100;",
87 | "payload": "",
88 | "payloadType": "date",
89 | "repeat": "10",
90 | "crontab": "",
91 | "once": false,
92 | "x": 120,
93 | "y": 300,
94 | "wires": [
95 | [
96 | "e2af09b3.78f348"
97 | ]
98 | ]
99 | },
100 | {
101 | "id": "f0db6199.dbd34",
102 | "type": "inject",
103 | "z": "e6691547.05bc98",
104 | "name": "delete records",
105 | "topic": "DELETE FROM RANDOMNUM WHERE TIMESTAMP <= strftime('%s','now', '-1 hours')*1000",
106 | "payload": "",
107 | "payloadType": "date",
108 | "repeat": "",
109 | "crontab": "",
110 | "once": false,
111 | "x": 130,
112 | "y": 200,
113 | "wires": [
114 | [
115 | "35881632.6e706a"
116 | ]
117 | ]
118 | },
119 | {
120 | "id": "1620e82a.be3b58",
121 | "type": "inject",
122 | "z": "e6691547.05bc98",
123 | "name": "show counts ",
124 | "topic": "SELECT COUNT(*) FROM RANDOMNUM",
125 | "payload": "",
126 | "payloadType": "date",
127 | "repeat": "",
128 | "crontab": "",
129 | "once": false,
130 | "x": 130,
131 | "y": 240,
132 | "wires": [
133 | [
134 | "35881632.6e706a"
135 | ]
136 | ]
137 | },
138 | {
139 | "id": "8284bec6.6187",
140 | "type": "ui_template",
141 | "z": "e6691547.05bc98",
142 | "group": "7a106693.b850b8",
143 | "name": "UI Table",
144 | "order": 1,
145 | "width": "",
146 | "height": "",
147 | "format": "\n \n Index | \n Timestamp | \n Value | \n Bool | \n
\n \n {{$index}} | \n {{msg.payload[$index].TIMESTAMP}} | \n {{msg.payload[$index].VALUE}} | \n {{msg.payload[$index].BOOL}} | \n
\n
",
148 | "storeOutMessages": true,
149 | "fwdInMessages": true,
150 | "x": 680,
151 | "y": 220,
152 | "wires": [
153 | []
154 | ]
155 | },
156 | {
157 | "id": "e2af09b3.78f348",
158 | "type": "litedb",
159 | "z": "e6691547.05bc98",
160 | "name": "",
161 | "x": 490,
162 | "y": 220,
163 | "wires": [
164 | [
165 | "8284bec6.6187"
166 | ]
167 | ]
168 | },
169 | {
170 | "id": "7a106693.b850b8",
171 | "type": "ui_group",
172 | "z": "",
173 | "name": "table",
174 | "tab": "a9cc4011.4f89a",
175 | "disp": true,
176 | "width": "6"
177 | },
178 | {
179 | "id": "a9cc4011.4f89a",
180 | "type": "ui_tab",
181 | "z": "",
182 | "name": "Home",
183 | "icon": "dashboard"
184 | }
185 | ]
--------------------------------------------------------------------------------
/arduino-mqtt/arduino_mqtt_sample.ino/arduino_mqtt_sample.ino.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "SoftwareSerial.h"
5 | #include
6 | #include "DHT.h"
7 |
8 | #define ESP_SSID "Your SSID"
9 | #define ESP_PASS "Your Wifi Password"
10 |
11 | #define mqtt_server "mqtt.sensetecnic.com"
12 | #define mqtt_port 1883
13 | #define mqtt_client_id "Your MQTT Client ID"
14 | #define mqtt_client_user "Your STS Username"
15 | #define mqtt_client_pw "Your MQTT Client Password"
16 | #define mqtt_client_topic_send_status "users//arduino/status"
17 | #define mqtt_client_topic_send_temperature "users//arduino/send/temperature"
18 | #define mqtt_client_topic_send_humidity "users//arduino/send/humidity"
19 | #define mqtt_client_topic_receive_led "users//L"
20 | #define birthMsg "Arduino Client connected"
21 | #define willMsg "Arduino Client disconnected"
22 |
23 | #define LEDpin 8
24 | #define DHTPIN 9
25 | #define DHTTYPE DHT22
26 | DHT dht(DHTPIN, DHTTYPE);
27 |
28 | String temp_str;
29 | String hum_str;
30 | char temp[50];
31 | char hum[50];
32 | float humidityReading; //Stores humidity value
33 | float temperatureReading; //Stores temperature value
34 | long lastMsg = 0;
35 | long lastLoop = 0;
36 |
37 | int status = WL_IDLE_STATUS; // the Wifi radio's status
38 |
39 | WiFiEspClient espClient;
40 |
41 | //print any message received for subscribed topic
42 | void callback(char* topic, byte* payload, unsigned int length) {
43 | Serial.print("Message arrived [");
44 | Serial.print(topic);
45 | Serial.print("] ");
46 | for (int i=0;i 15000) {
125 | lastMsg = now;
126 | sendData();
127 | }
128 |
129 | if (now - lastLoop > 200) {
130 | lastLoop = now;
131 | if (!client.connected()) {
132 | reconnect();
133 | }
134 | client.loop();
135 | }
136 | }
137 |
138 | void reconnect() {
139 | // Loop until we're reconnected
140 | while (!client.connected()) {
141 | Serial.print("Attempting MQTT connection...");
142 | // Attempt to connect, just a name to identify the client
143 | if (client.connect(mqtt_client_id, mqtt_client_user, mqtt_client_pw, mqtt_client_topic_send_status, 1, 1, willMsg)) {
144 | Serial.println("connected");
145 | client.publish(mqtt_client_topic_send_status, birthMsg);
146 | Serial.println(client.subscribe(mqtt_client_topic_receive_led));
147 |
148 | } else {
149 | Serial.print("failed, rc=");
150 | Serial.print(client.state());
151 | Serial.println(" try again in 5 seconds");
152 | // Wait 5 seconds before retrying
153 | delay(5000);
154 | }
155 | }
156 | }
157 |
158 |
--------------------------------------------------------------------------------
/arduino-mqtt/sample-flow-on-fred.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "ccb4b575.ddba08",
4 | "type": "inject",
5 | "z": "723f3ce1.b62d34",
6 | "name": "",
7 | "topic": "",
8 | "payload": "1",
9 | "payloadType": "num",
10 | "repeat": "",
11 | "crontab": "",
12 | "once": false,
13 | "x": 266,
14 | "y": 284,
15 | "wires": [
16 | [
17 | "21c937c3.94c418"
18 | ]
19 | ]
20 | },
21 | {
22 | "id": "21c937c3.94c418",
23 | "type": "sts-mqtt-out",
24 | "z": "723f3ce1.b62d34",
25 | "name": "",
26 | "topic": "users/YourUsername/L",
27 | "qos": "",
28 | "retain": "",
29 | "broker": "38670a75.d27f66",
30 | "x": 470,
31 | "y": 375,
32 | "wires": []
33 | },
34 | {
35 | "id": "4b7ff3e7.ed031c",
36 | "type": "inject",
37 | "z": "723f3ce1.b62d34",
38 | "name": "",
39 | "topic": "",
40 | "payload": "0",
41 | "payloadType": "num",
42 | "repeat": "",
43 | "crontab": "",
44 | "once": false,
45 | "x": 238,
46 | "y": 367,
47 | "wires": [
48 | [
49 | "21c937c3.94c418"
50 | ]
51 | ]
52 | },
53 | {
54 | "id": "fc61b397.902b3",
55 | "type": "sts-mqtt-in",
56 | "z": "723f3ce1.b62d34",
57 | "name": "",
58 | "topic": "users/YourUsername/arduino/send/temperature",
59 | "qos": "2",
60 | "broker": "38670a75.d27f66",
61 | "x": 359,
62 | "y": 575,
63 | "wires": [
64 | [
65 | "44d69885.3a0b68",
66 | "3b03cca5.64de74"
67 | ]
68 | ]
69 | },
70 | {
71 | "id": "aa75a4dd.fe7208",
72 | "type": "sts-mqtt-in",
73 | "z": "723f3ce1.b62d34",
74 | "name": "",
75 | "topic": "users/YourUsername/arduino/send/humidity",
76 | "qos": "2",
77 | "broker": "38670a75.d27f66",
78 | "x": 378,
79 | "y": 639,
80 | "wires": [
81 | [
82 | "9efa9d08.4d545",
83 | "a704b460.efb388"
84 | ]
85 | ]
86 | },
87 | {
88 | "id": "44d69885.3a0b68",
89 | "type": "debug",
90 | "z": "723f3ce1.b62d34",
91 | "name": "",
92 | "active": true,
93 | "console": "false",
94 | "complete": "false",
95 | "x": 626,
96 | "y": 575,
97 | "wires": []
98 | },
99 | {
100 | "id": "9efa9d08.4d545",
101 | "type": "debug",
102 | "z": "723f3ce1.b62d34",
103 | "name": "",
104 | "active": true,
105 | "console": "false",
106 | "complete": "false",
107 | "x": 617,
108 | "y": 634,
109 | "wires": []
110 | },
111 | {
112 | "id": "3b03cca5.64de74",
113 | "type": "change",
114 | "z": "723f3ce1.b62d34",
115 | "name": "",
116 | "rules": [
117 | {
118 | "t": "set",
119 | "p": "topic",
120 | "pt": "msg",
121 | "to": "Temperature",
122 | "tot": "str"
123 | }
124 | ],
125 | "action": "",
126 | "property": "",
127 | "from": "",
128 | "to": "",
129 | "reg": false,
130 | "x": 564,
131 | "y": 702,
132 | "wires": [
133 | [
134 | "9d0c8f10.a0f3c"
135 | ]
136 | ]
137 | },
138 | {
139 | "id": "a704b460.efb388",
140 | "type": "change",
141 | "z": "723f3ce1.b62d34",
142 | "name": "",
143 | "rules": [
144 | {
145 | "t": "set",
146 | "p": "topic",
147 | "pt": "msg",
148 | "to": "Humidity",
149 | "tot": "str"
150 | }
151 | ],
152 | "action": "",
153 | "property": "",
154 | "from": "",
155 | "to": "",
156 | "reg": false,
157 | "x": 543,
158 | "y": 753,
159 | "wires": [
160 | [
161 | "9d0c8f10.a0f3c"
162 | ]
163 | ]
164 | },
165 | {
166 | "id": "9d0c8f10.a0f3c",
167 | "type": "ui_chart",
168 | "z": "723f3ce1.b62d34",
169 | "name": "",
170 | "group": "953faf60.3138c",
171 | "order": 0,
172 | "width": 0,
173 | "height": 0,
174 | "label": "Arduino MQTT",
175 | "chartType": "line",
176 | "legend": "true",
177 | "xformat": "HH:mm:ss",
178 | "interpolate": "linear",
179 | "nodata": "",
180 | "ymin": "",
181 | "ymax": "",
182 | "removeOlder": 1,
183 | "removeOlderPoints": "",
184 | "removeOlderUnit": "86400",
185 | "cutout": 0,
186 | "colors": [
187 | "#1f77b4",
188 | "#aec7e8",
189 | "#ff7f0e",
190 | "#2ca02c",
191 | "#98df8a",
192 | "#d62728",
193 | "#ff9896",
194 | "#9467bd",
195 | "#c5b0d5"
196 | ],
197 | "x": 746,
198 | "y": 731,
199 | "wires": [
200 | [],
201 | []
202 | ]
203 | },
204 | {
205 | "id": "38670a75.d27f66",
206 | "type": "sts-mqtt-broker",
207 | "z": "",
208 | "broker": "mqtt.sensetecnic.com",
209 | "port": "8883",
210 | "clientid": "YOUR CLIENT ID",
211 | "usetls": true,
212 | "enableWillMsg": false,
213 | "willTopic": "",
214 | "willQos": "0",
215 | "willPayload": "",
216 | "enableBirthMsg": false,
217 | "birthTopic": "",
218 | "birthQos": "0",
219 | "birthPayload": ""
220 | },
221 | {
222 | "id": "953faf60.3138c",
223 | "type": "ui_group",
224 | "z": "",
225 | "name": "Default",
226 | "tab": "c25fb91f.0f42f8",
227 | "disp": true,
228 | "width": "12"
229 | },
230 | {
231 | "id": "c25fb91f.0f42f8",
232 | "type": "ui_tab",
233 | "z": "",
234 | "name": "Arduino reading",
235 | "icon": "dashboard",
236 | "order": 1
237 | }
238 | ]
--------------------------------------------------------------------------------
/connecting-device-to-cloud/receive-from-cloud-via-rjlTest2.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "b50e2f45.056d",
4 | "type": "fred in",
5 | "z": "87394a82.590968",
6 | "name": "Receive from Cloud Via rjlTest2",
7 | "server": "586ff0dd.14abc",
8 | "client": "",
9 | "x": 212.5,
10 | "y": 208,
11 | "wires": [
12 | [
13 | "7de22e43.008"
14 | ]
15 | ]
16 | },
17 | {
18 | "id": "7de22e43.008",
19 | "type": "debug",
20 | "z": "87394a82.590968",
21 | "name": "",
22 | "active": true,
23 | "console": "false",
24 | "complete": "false",
25 | "x": 379.5,
26 | "y": 263,
27 | "wires": []
28 | },
29 | {
30 | "id": "586ff0dd.14abc",
31 | "type": "fred-server",
32 | "z": "87394a82.590968",
33 | "endpoint": "rjlTest2",
34 | "private": false,
35 | "wholemsg": "false"
36 | }
37 | ]
--------------------------------------------------------------------------------
/connecting-device-to-cloud/talk-to-device-on-rjlTest.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "5ad6ea.ff92d918",
4 | "type": "fred in",
5 | "z": "87394a82.590968",
6 | "name": "Talk do device",
7 | "server": "2344090e.b7f726",
8 | "client": "",
9 | "x": 169.5,
10 | "y": 167,
11 | "wires": [
12 | [
13 | "9eee73e7.8962"
14 | ]
15 | ]
16 | },
17 | {
18 | "id": "9eee73e7.8962",
19 | "type": "debug",
20 | "z": "87394a82.590968",
21 | "name": "",
22 | "active": true,
23 | "console": "false",
24 | "complete": "false",
25 | "x": 330.5,
26 | "y": 213,
27 | "wires": []
28 | },
29 | {
30 | "id": "2344090e.b7f726",
31 | "type": "fred-server",
32 | "z": "87394a82.590968",
33 | "endpoint": "rjlTest",
34 | "private": false,
35 | "wholemsg": "false"
36 | }
37 | ]
--------------------------------------------------------------------------------
/connecting-device-to-cloud/talk-to-server-on-rjlTest.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "c74b0e90.cb017",
4 | "type": "fred out",
5 | "z": "87394a82.590968",
6 | "name": "Talk to FRED on rjlTest",
7 | "server": "2344090e.b7f726",
8 | "client": "",
9 | "x": 363.5,
10 | "y": 206,
11 | "wires": []
12 | },
13 | {
14 | "id": "6a996160.9a14d",
15 | "type": "inject",
16 | "z": "87394a82.590968",
17 | "name": "",
18 | "topic": "",
19 | "payload": "",
20 | "payloadType": "date",
21 | "repeat": "",
22 | "crontab": "",
23 | "once": false,
24 | "x": 138.5,
25 | "y": 147,
26 | "wires": [
27 | [
28 | "c74b0e90.cb017"
29 | ]
30 | ]
31 | },
32 | {
33 | "id": "2344090e.b7f726",
34 | "type": "fred-server",
35 | "z": "87394a82.590968",
36 | "endpoint": "rjlTest",
37 | "private": false,
38 | "wholemsg": "false"
39 | }
40 | ]
--------------------------------------------------------------------------------
/multitech-lorawan-gateway-fred/FRED-receiver-and-forward-to-telegram.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "8dc31f49.e8a1d",
4 | "type": "function",
5 | "z": "e0580e83.09a8f",
6 | "name": "read data from handheld tool gps",
7 | "func": "var data_type = {\n\tnone_0 : 0,\n\ttemp_curr : 1,\n\tnone_1 : 2,\n\tgps_latitude : 3,\n\tgps_longitude : 7\n};\n\nvar gps_decode_index = 2147483647;\n\nvar data_struc = {\n\ttemperature : 0,\n\tlat_deg : 0 ,\n\tlong_deg : 0,\n};\n\npData = data_struc;\nvar msg_pntr = 0;\nvar temp = 0;\n\nvar loraPacket = msg.payload.payload;\n\nwhile (msg_pntr < loraPacket.length){\n \n\tswitch (msg_pntr){\n case data_type.none_0:\n msg_pntr++;\n \t\tbreak;\n case data_type.none_1:\n msg_pntr++;\n \t\tbreak;\n \tcase data_type.temp_curr:\n \t\tpData.temperature = (loraPacket[msg_pntr] << 16) >> 16;\n \t\tmsg_pntr++;\n \t\tbreak;\n\n \tcase data_type.gps_latitude:\n pData.lat_deg = parseInt(loraPacket.toString('hex', 3, 7), 16);\n pData.lat_deg = pData.lat_deg/gps_decode_index * 90\n if (pData.lat_deg > 90) {\n pData.lat_deg = pData.lat_deg - 90\n }\n \t\tmsg_pntr += 4;\n \t\tbreak;\n \tcase data_type.gps_longitude:\n pData.long_deg = parseInt(loraPacket.toString('hex', 7, 11), 16);\n pData.long_deg = pData.long_deg/gps_decode_index * 180;\n if (pData.long_deg > 180) {\n pData.long_deg = pData.long_deg - 360\n }\n msg_pntr += 4;\n \t\tbreak;\n\tdefault:\n\t\tmsg_pntr++;\n\t}\n}\n\n\nmsg.pData = pData;\n\nreturn {payload:msg};",
8 | "outputs": 1,
9 | "noerr": 0,
10 | "x": 480,
11 | "y": 400,
12 | "wires": [
13 | [
14 | "588f722f.4bed8c"
15 | ]
16 | ]
17 | },
18 | {
19 | "id": "f852b820.388478",
20 | "type": "sts-mqtt-in",
21 | "z": "e0580e83.09a8f",
22 | "name": "",
23 | "topic": "users/demouser/lorawan",
24 | "qos": "2",
25 | "broker": "2f09be8b.c1e352",
26 | "x": 190,
27 | "y": 400,
28 | "wires": [
29 | [
30 | "8dc31f49.e8a1d"
31 | ]
32 | ]
33 | },
34 | {
35 | "id": "588f722f.4bed8c",
36 | "type": "function",
37 | "z": "e0580e83.09a8f",
38 | "name": "prepare ttn content to send back to telegram",
39 | "func": "var telegram=flow.get('telegram')|| {};\n\n\ntelegram.payload.content = msg;\n\nreturn telegram;",
40 | "outputs": 1,
41 | "noerr": 0,
42 | "x": 830,
43 | "y": 400,
44 | "wires": [
45 | [
46 | "efc1430c.dd142"
47 | ]
48 | ]
49 | },
50 | {
51 | "id": "efc1430c.dd142",
52 | "type": "chatbot-telegram-send",
53 | "z": "e0580e83.09a8f",
54 | "bot": "5687554f.8e27ec",
55 | "track": false,
56 | "outputs": 0,
57 | "x": 970,
58 | "y": 500,
59 | "wires": []
60 | },
61 | {
62 | "id": "7fc8aca5.7b17f4",
63 | "type": "chatbot-telegram-receive",
64 | "z": "e0580e83.09a8f",
65 | "bot": "5687554f.8e27ec",
66 | "x": 210,
67 | "y": 500,
68 | "wires": [
69 | [
70 | "4ce9727d.b695fc"
71 | ]
72 | ]
73 | },
74 | {
75 | "id": "4ce9727d.b695fc",
76 | "type": "function",
77 | "z": "e0580e83.09a8f",
78 | "name": "save msg",
79 | "func": "flow.set('telegram', msg);\nreturn msg;",
80 | "outputs": 1,
81 | "noerr": 0,
82 | "x": 601,
83 | "y": 499,
84 | "wires": [
85 | [
86 | "efc1430c.dd142"
87 | ]
88 | ]
89 | },
90 | {
91 | "id": "f46da79a.de7598",
92 | "type": "comment",
93 | "z": "e0580e83.09a8f",
94 | "name": "receive msg from STS-MQTT, decode the buffer LoRaWAN msg",
95 | "info": "",
96 | "x": 370,
97 | "y": 340,
98 | "wires": []
99 | },
100 | {
101 | "id": "a0ac3f1.5f93ec",
102 | "type": "comment",
103 | "z": "e0580e83.09a8f",
104 | "name": "set up telegram to view msg on phone",
105 | "info": "1. You need to setup the bot on telegram. \n You might be able to fine more info here:https://telegram.org/blog/bot-revolution\n\n2. In order to send message to telegram, we need msg id, token etc.\n So we need to store an initial msg from our phone in global context,\n and then replace the new msg into the payload content of the stored msg.\n",
106 | "x": 390,
107 | "y": 460,
108 | "wires": []
109 | },
110 | {
111 | "id": "2f09be8b.c1e352",
112 | "type": "sts-mqtt-broker",
113 | "z": "",
114 | "broker": "mqtt.sensetecnic.com",
115 | "port": "8883",
116 | "clientid": "demouser_client_id",
117 | "usetls": true,
118 | "enableWillMsg": false,
119 | "willTopic": "",
120 | "willQos": "0",
121 | "willPayload": "",
122 | "enableBirthMsg": false,
123 | "birthTopic": "",
124 | "birthQos": "0",
125 | "birthPayload": ""
126 | },
127 | {
128 | "id": "5687554f.8e27ec",
129 | "type": "chatbot-telegram-node",
130 | "z": "",
131 | "botname": "sts_testing_bot",
132 | "usernames": "",
133 | "polling": "1000",
134 | "log": ""
135 | }
136 | ]
--------------------------------------------------------------------------------
/multitech-lorawan-gateway-fred/gateway-node-red.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "e437effd.12795",
4 | "type": "lora in",
5 | "z": "2ef93b9f.1927b4",
6 | "name": "",
7 | "datatype": "bytes",
8 | "x": 280,
9 | "y": 360,
10 | "wires": [
11 | [
12 | "e3bb8ee3.fe298"
13 | ]
14 | ]
15 | },
16 | {
17 | "id": "5fc36e31.3b4fd",
18 | "type": "mqtt out",
19 | "z": "2ef93b9f.1927b4",
20 | "name": "",
21 | "topic": "users/demouser/lorawan",
22 | "qos": "",
23 | "retain": "true",
24 | "broker": "48375ddc.656bc4",
25 | "x": 670,
26 | "y": 360,
27 | "wires": []
28 | },
29 | {
30 | "id": "d06a08ee.9de868",
31 | "type": "comment",
32 | "z": "2ef93b9f.1927b4",
33 | "name": "forward lorawan packets to STS-MQTT",
34 | "info": "",
35 | "x": 470,
36 | "y": 300,
37 | "wires": []
38 | },
39 | {
40 | "id": "e3bb8ee3.fe298",
41 | "type": "function",
42 | "z": "2ef93b9f.1927b4",
43 | "name": "",
44 | "func": "var newMsg = {\n payload: msg \n};\nreturn newMsg;",
45 | "outputs": 1,
46 | "noerr": 0,
47 | "x": 450,
48 | "y": 360,
49 | "wires": [
50 | [
51 | "5fc36e31.3b4fd"
52 | ]
53 | ]
54 | },
55 | {
56 | "id": "48375ddc.656bc4",
57 | "type": "mqtt-broker",
58 | "z": "",
59 | "broker": "mqtt.sensetecnic.com",
60 | "port": "8883",
61 | "tls": "218ac345.4cb98c",
62 | "clientid": "",
63 | "usetls": true,
64 | "compatmode": true,
65 | "keepalive": "60",
66 | "cleansession": true,
67 | "willTopic": "",
68 | "willQos": "0",
69 | "willPayload": "",
70 | "birthTopic": "",
71 | "birthQos": "0",
72 | "birthPayload": ""
73 | },
74 | {
75 | "id": "218ac345.4cb98c",
76 | "type": "tls-config",
77 | "z": "",
78 | "name": "",
79 | "cert": "",
80 | "key": "",
81 | "ca": "",
82 | "certname": "",
83 | "keyname": "",
84 | "caname": "",
85 | "verifyservercert": false
86 | }
87 | ]
--------------------------------------------------------------------------------
/multitech-lorawan-gateway-fred/generate-map.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "11da1036.e0c13",
4 | "type": "inject",
5 | "z": "2ac899e4.08caf6",
6 | "name": "",
7 | "topic": "",
8 | "payload": "",
9 | "payloadType": "date",
10 | "repeat": "",
11 | "crontab": "",
12 | "once": false,
13 | "x": 120,
14 | "y": 300,
15 | "wires": [
16 | [
17 | "58a23b3d.008344",
18 | "73f59189.1d72a"
19 | ]
20 | ]
21 | },
22 | {
23 | "id": "58a23b3d.008344",
24 | "type": "http request",
25 | "z": "2ac899e4.08caf6",
26 | "name": "",
27 | "method": "GET",
28 | "ret": "txt",
29 | "url": "",
30 | "tls": "218ac345.4cb98c",
31 | "x": 270,
32 | "y": 300,
33 | "wires": [
34 | [
35 | "d7661424.0b6bf8"
36 | ]
37 | ]
38 | },
39 | {
40 | "id": "d7661424.0b6bf8",
41 | "type": "csv",
42 | "z": "2ac899e4.08caf6",
43 | "name": "",
44 | "sep": ",",
45 | "hdrin": "",
46 | "hdrout": "",
47 | "multi": "one",
48 | "ret": "\\n",
49 | "temp": "lat, lon, rssi, data-rate, name",
50 | "x": 410,
51 | "y": 300,
52 | "wires": [
53 | [
54 | "eb2b831.af7538"
55 | ]
56 | ]
57 | },
58 | {
59 | "id": "eb2b831.af7538",
60 | "type": "worldmap",
61 | "z": "2ac899e4.08caf6",
62 | "name": "",
63 | "lat": "49.266173",
64 | "lon": "-123.098",
65 | "zoom": "",
66 | "layer": "OSM",
67 | "cluster": "",
68 | "maxage": "",
69 | "x": 610,
70 | "y": 300,
71 | "wires": []
72 | },
73 | {
74 | "id": "73f59189.1d72a",
75 | "type": "function",
76 | "z": "2ac899e4.08caf6",
77 | "name": "base station",
78 | "func": "msg.payload = {\n name: 'Base station',\n lat:49.266173,\n lon:-123.098693\n}\nreturn msg;",
79 | "outputs": 1,
80 | "noerr": 0,
81 | "x": 310,
82 | "y": 360,
83 | "wires": [
84 | [
85 | "eb2b831.af7538"
86 | ]
87 | ]
88 | },
89 | {
90 | "id": "769778ed.7757d8",
91 | "type": "comment",
92 | "z": "2ac899e4.08caf6",
93 | "name": "generage map ",
94 | "info": "We had previously stored all data on a CSV file to show the data points.\nYou can store your data the same way or save them onto a database,\nand generate the datapoints the way you want. \n\nWe had ommited the csv file in this sample flow, but you can see the result \nimage to have an idea. ",
95 | "x": 307.77777777777777,
96 | "y": 235.55555555555554,
97 | "wires": []
98 | },
99 | {
100 | "id": "218ac345.4cb98c",
101 | "type": "tls-config",
102 | "z": "",
103 | "name": "",
104 | "cert": "",
105 | "key": "",
106 | "ca": "",
107 | "certname": "",
108 | "keyname": "",
109 | "caname": "",
110 | "verifyservercert": false
111 | }
112 | ]
113 |
--------------------------------------------------------------------------------
/multitech-lorawan-gateway-fred/map-screen-shot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SenseTecnic/tutorial-samples/99a6d45b1150e802c511c277764ae7eda9aaa670/multitech-lorawan-gateway-fred/map-screen-shot.png
--------------------------------------------------------------------------------
/node-red-contrib-dashboard/node-red-contrib-dashboard-sample.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "ff9fafff.553ec",
4 | "type": "inject",
5 | "z": "50b043f1.129efc",
6 | "name": "",
7 | "topic": "",
8 | "payload": "",
9 | "payloadType": "date",
10 | "repeat": "5",
11 | "crontab": "",
12 | "once": false,
13 | "x": 108,
14 | "y": 128,
15 | "wires": [
16 | [
17 | "33c90cf1.7f67b4"
18 | ]
19 | ]
20 | },
21 | {
22 | "id": "33c90cf1.7f67b4",
23 | "type": "function",
24 | "z": "50b043f1.129efc",
25 | "name": "Random number",
26 | "func": "msg.payload = Math.round(Math.random()*100);\nreturn msg;",
27 | "outputs": 1,
28 | "noerr": 0,
29 | "x": 254,
30 | "y": 195,
31 | "wires": [
32 | [
33 | "ac7a5b30.c88c38",
34 | "7ddd4a0d.3fdf84",
35 | "41693a34.1aa2f4",
36 | "cc747179.ae834"
37 | ]
38 | ]
39 | },
40 | {
41 | "id": "ac7a5b30.c88c38",
42 | "type": "ui_chart",
43 | "z": "50b043f1.129efc",
44 | "name": "",
45 | "group": "b331f28d.abb6d",
46 | "order": 0,
47 | "width": 0,
48 | "height": 0,
49 | "label": "chart",
50 | "chartType": "line",
51 | "legend": "false",
52 | "xformat": "%H:%M:%S",
53 | "interpolate": "linear",
54 | "nodata": "",
55 | "ymin": "",
56 | "ymax": "",
57 | "removeOlder": "5",
58 | "removeOlderUnit": "60",
59 | "x": 455,
60 | "y": 214,
61 | "wires": [
62 | [],
63 | []
64 | ]
65 | },
66 | {
67 | "id": "7ddd4a0d.3fdf84",
68 | "type": "ui_gauge",
69 | "z": "50b043f1.129efc",
70 | "name": "",
71 | "group": "b331f28d.abb6d",
72 | "order": 0,
73 | "width": 0,
74 | "height": 0,
75 | "gtype": "gage",
76 | "title": "Gauge",
77 | "label": "units",
78 | "format": "{{value}}",
79 | "min": 0,
80 | "max": "100",
81 | "colors": [
82 | "#00b500",
83 | "#e6e600",
84 | "#ca3838"
85 | ],
86 | "x": 461,
87 | "y": 277,
88 | "wires": []
89 | },
90 | {
91 | "id": "41693a34.1aa2f4",
92 | "type": "ui_slider",
93 | "z": "50b043f1.129efc",
94 | "name": "",
95 | "label": "slider",
96 | "group": "86ec7e92.eeb6a",
97 | "order": 0,
98 | "width": 0,
99 | "height": 0,
100 | "passthru": true,
101 | "topic": "",
102 | "min": 0,
103 | "max": "100",
104 | "x": 462,
105 | "y": 346,
106 | "wires": [
107 | []
108 | ]
109 | },
110 | {
111 | "id": "cc747179.ae834",
112 | "type": "ui_text",
113 | "z": "50b043f1.129efc",
114 | "group": "86ec7e92.eeb6a",
115 | "order": 0,
116 | "width": 0,
117 | "height": 0,
118 | "name": "",
119 | "label": "text",
120 | "format": "{{msg.payload}}",
121 | "layout": "row-spread",
122 | "x": 465,
123 | "y": 404,
124 | "wires": []
125 | },
126 | {
127 | "id": "b331f28d.abb6d",
128 | "type": "ui_group",
129 | "z": "50b043f1.129efc",
130 | "name": "Default",
131 | "tab": "2821c665.04410a",
132 | "disp": true,
133 | "width": "6"
134 | },
135 | {
136 | "id": "86ec7e92.eeb6a",
137 | "type": "ui_group",
138 | "z": "50b043f1.129efc",
139 | "name": "anotherWidget",
140 | "tab": "2821c665.04410a",
141 | "disp": true,
142 | "width": "6"
143 | },
144 | {
145 | "id": "2821c665.04410a",
146 | "type": "ui_tab",
147 | "z": "50b043f1.129efc",
148 | "name": "Home",
149 | "icon": "dashboard"
150 | }
151 | ]
--------------------------------------------------------------------------------
/opc-ua-sample-flow/OPC Painting Demo.opf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SenseTecnic/tutorial-samples/99a6d45b1150e802c511c277764ae7eda9aaa670/opc-ua-sample-flow/OPC Painting Demo.opf
--------------------------------------------------------------------------------
/post-data-to-dweetio-using-fred/post-data-to-dweetio-using-fred.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "959cc1ad.87437",
4 | "type": "inject",
5 | "z": "87394a82.590968",
6 | "name": "",
7 | "topic": "",
8 | "payload": "Hello from FRED",
9 | "payloadType": "str",
10 | "repeat": "",
11 | "crontab": "",
12 | "once": false,
13 | "x": 133,
14 | "y": 103,
15 | "wires": [
16 | [
17 | "57924bd.df9f6b4"
18 | ]
19 | ]
20 | },
21 | {
22 | "id": "57924bd.df9f6b4",
23 | "type": "dweetio out",
24 | "z": "87394a82.590968",
25 | "thing": "thingName",
26 | "name": "",
27 | "x": 245,
28 | "y": 160,
29 | "wires": []
30 | },
31 | {
32 | "id": "b02c3f87.4a12f",
33 | "type": "dweetio in",
34 | "z": "87394a82.590968",
35 | "thing": "thingName",
36 | "name": "",
37 | "x": 130,
38 | "y": 248,
39 | "wires": [
40 | [
41 | "f33744b6.d61dc8"
42 | ]
43 | ]
44 | },
45 | {
46 | "id": "f33744b6.d61dc8",
47 | "type": "debug",
48 | "z": "87394a82.590968",
49 | "name": "",
50 | "active": true,
51 | "console": "false",
52 | "complete": "false",
53 | "x": 296,
54 | "y": 280,
55 | "wires": []
56 | }
57 | ]
--------------------------------------------------------------------------------
/ttn-feather-m0/feather-m0-ttn-abp-works-with-multitech-with-sensors/feather-m0-ttn-abp-works-with-multitech-with-sensors.ino:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman
3 | *
4 | * Permission is hereby granted, free of charge, to anyone
5 | * obtaining a copy of this document and accompanying files,
6 | * to do whatever they want with them without any restriction,
7 | * including, but not limited to, copying, modification and redistribution.
8 | * NO WARRANTY OF ANY KIND IS PROVIDED.
9 | *
10 | * This arduino code is modified to use with feather M0 with LoRaWan by Michael Qiu
11 | * More documentation can be found on http://developers.sensetecnic.com/article/use-fred-with-lorawan/
12 | *
13 | * This uses ABP (Activation-by-personalisation), where a DevAddr and
14 | * Session keys are preconfigured (unlike OTAA, where a DevEUI and
15 | * application key is configured, while the DevAddr and session keys are
16 | * assigned/generated in the over-the-air-activation procedure).
17 | *
18 | * Note: LoRaWAN per sub-band duty-cycle limitation is enforced (1% in
19 | * g1, 0.1% in g2), but not the TTN fair usage policy (which is probably
20 | * violated by this sketch when left running for longer)!
21 | *
22 | * To use this sketch, first register your application and device with
23 | * the things network, to set or generate a DevAddr, NwkSKey and
24 | * AppSKey. Each device should have their own unique values for these
25 | * fields.
26 | *
27 | * Do not forget to define the radio type correctly in config.h.
28 | *
29 | *******************************************************************************/
30 |
31 | #include
32 | #include
33 | #include
34 | #include "DHT.h"
35 | #include
36 | #include
37 | #include
38 |
39 | #define DHTPIN 15
40 | #define DHTTYPE DHT22
41 | DHT dht(DHTPIN, DHTTYPE);
42 | int BH1750_address = 0x23; // i2c Addresse
43 | byte buff[2];
44 |
45 | LiquidCrystal lcd(12, 11, 16, 17, 18, 19);
46 |
47 | // LoRaWAN NwkSKey, network session key
48 | // This is the default Semtech key, which is used by the early prototype TTN
49 | // network.
50 | static const PROGMEM u1_t NWKSKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
51 |
52 | // LoRaWAN AppSKey, application session key
53 | // This is the default Semtech key, which is used by the early prototype TTN
54 | // network.
55 | static const u1_t PROGMEM APPSKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
56 |
57 | // LoRaWAN end-device address (DevAddr)
58 | static const u4_t DEVADDR = 0x00000000 ; // <-- Change this address for every node!
59 |
60 | // These callbacks are only used in over-the-air activation, so they are
61 | // left empty here (we cannot leave them out completely unless
62 | // DISABLE_JOIN is set in config.h, otherwise the linker will complain).
63 | void os_getArtEui (u1_t* buf) { }
64 | void os_getDevEui (u1_t* buf) { }
65 | void os_getDevKey (u1_t* buf) { }
66 |
67 | static uint8_t mydata[] = "";
68 | static osjob_t sendjob;
69 |
70 | // Schedule TX every this many seconds (might become longer due to duty
71 | // cycle limitations).
72 | const unsigned TX_INTERVAL = 60;
73 |
74 | // Pin mapping
75 | const lmic_pinmap lmic_pins = {
76 |
77 | .nss = 8, // Internal connected
78 | .rxtx = LMIC_UNUSED_PIN,
79 | .rst = 4, // Internal connected
80 | .dio = {3, 5, 6}, // Connect "i01" to "5"
81 | };
82 |
83 | void onEvent (ev_t ev) {
84 | Serial.print(os_getTime());
85 | Serial.print(": ");
86 | switch(ev) {
87 | case EV_SCAN_TIMEOUT:
88 | Serial.println(F("EV_SCAN_TIMEOUT"));
89 | break;
90 | case EV_BEACON_FOUND:
91 | Serial.println(F("EV_BEACON_FOUND"));
92 | break;
93 | case EV_BEACON_MISSED:
94 | Serial.println(F("EV_BEACON_MISSED"));
95 | break;
96 | case EV_BEACON_TRACKED:
97 | Serial.println(F("EV_BEACON_TRACKED"));
98 | break;
99 | case EV_JOINING:
100 | Serial.println(F("EV_JOINING"));
101 | break;
102 | case EV_JOINED:
103 | Serial.println(F("EV_JOINED"));
104 | break;
105 | case EV_RFU1:
106 | Serial.println(F("EV_RFU1"));
107 | break;
108 | case EV_JOIN_FAILED:
109 | Serial.println(F("EV_JOIN_FAILED"));
110 | break;
111 | case EV_REJOIN_FAILED:
112 | Serial.println(F("EV_REJOIN_FAILED"));
113 | break;
114 | case EV_TXCOMPLETE:
115 | Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
116 | if (LMIC.txrxFlags & TXRX_ACK)
117 | Serial.println(F("Received ack"));
118 | if (LMIC.dataLen) {
119 | Serial.println(F("Received "));
120 | Serial.println(LMIC.dataLen);
121 | Serial.println(F(" bytes of payload"));
122 | }
123 | // Schedule next transmission
124 | os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
125 | break;
126 | case EV_LOST_TSYNC:
127 | Serial.println(F("EV_LOST_TSYNC"));
128 | break;
129 | case EV_RESET:
130 | Serial.println(F("EV_RESET"));
131 | break;
132 | case EV_RXCOMPLETE:
133 | // data received in ping slot
134 | Serial.println(F("EV_RXCOMPLETE"));
135 | break;
136 | case EV_LINK_DEAD:
137 | Serial.println(F("EV_LINK_DEAD"));
138 | break;
139 | case EV_LINK_ALIVE:
140 | Serial.println(F("EV_LINK_ALIVE"));
141 | break;
142 | default:
143 | Serial.println(F("Unknown event"));
144 | break;
145 | }
146 | }
147 |
148 | void do_send(osjob_t* j){
149 | // Check if there is not a current TX/RX job running
150 | if (LMIC.opmode & OP_TXRXPEND) {
151 | Serial.println(F("OP_TXRXPEND, not sending"));
152 | } else {
153 | prepareData();
154 | // Prepare upstream data transmission at the next possible time.
155 | LMIC_setTxData2(1, mydata, 20, 0);
156 | Serial.println(F("Packet queued"));
157 | }
158 | // Next TX is scheduled after TX_COMPLETE event.
159 | }
160 |
161 | void setup() {
162 | Serial.begin(115200);
163 | Serial.println(F("Starting"));
164 |
165 | #ifdef VCC_ENABLE
166 | // For Pinoccio Scout boards
167 | pinMode(VCC_ENABLE, OUTPUT);
168 | digitalWrite(VCC_ENABLE, HIGH);
169 | delay(1000);
170 | #endif
171 |
172 | // LMIC init
173 | os_init();
174 | // Reset the MAC state. Session and pending data transfers will be discarded.
175 | LMIC_reset();
176 |
177 | // Set static session parameters. Instead of dynamically establishing a session
178 | // by joining the network, precomputed session parameters are be provided.
179 | #ifdef PROGMEM
180 | // On AVR, these values are stored in flash and only copied to RAM
181 | // once. Copy them to a temporary buffer here, LMIC_setSession will
182 | // copy them into a buffer of its own again.
183 | uint8_t appskey[sizeof(APPSKEY)];
184 | uint8_t nwkskey[sizeof(NWKSKEY)];
185 | memcpy_P(appskey, APPSKEY, sizeof(APPSKEY));
186 | memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY));
187 | LMIC_setSession (0x1, DEVADDR, nwkskey, appskey);
188 | #else
189 | // If not running an AVR with PROGMEM, just use the arrays directly
190 | LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY);
191 | #endif
192 |
193 | #if defined(CFG_eu868)
194 | // Set up the channels used by the Things Network, which corresponds
195 | // to the defaults of most gateways. Without this, only three base
196 | // channels from the LoRaWAN specification are used, which certainly
197 | // works, so it is good for debugging, but can overload those
198 | // frequencies, so be sure to configure the full frequency range of
199 | // your network here (unless your network autoconfigures them).
200 | // Setting up channels should happen after LMIC_setSession, as that
201 | // configures the minimal channel set.
202 | // NA-US channels 0-71 are configured automatically
203 | LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
204 | LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI); // g-band
205 | LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
206 | LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
207 | LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
208 | LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
209 | LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
210 | LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
211 | LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK, DR_FSK), BAND_MILLI); // g2-band
212 | // TTN defines an additional channel at 869.525Mhz using SF9 for class B
213 | // devices' ping slots. LMIC does not have an easy way to define set this
214 | // frequency and support for class B is spotty and untested, so this
215 | // frequency is not configured here.
216 | #elif defined(CFG_us915)
217 | // NA-US channels 0-71 are configured automatically
218 | // but only one group of 8 should (a subband) should be active
219 | // TTN recommends the second sub band, 1 in a zero based count.
220 | // https://github.com/TheThingsNetwork/gateway-conf/blob/master/US-global_conf.json
221 | LMIC_selectSubBand(1);
222 | #endif
223 |
224 | // Disable link check validation
225 | LMIC_setLinkCheckMode(0);
226 |
227 | // TTN uses SF9 for its RX2 window.
228 | LMIC.dn2Dr = DR_SF9;
229 |
230 | // Set data rate and transmit power for uplink (note: txpow seems to be ignored by the library)
231 | LMIC_setDrTxpow(DR_SF7,14);
232 |
233 | Wire.begin();
234 | BH1750_Init(BH1750_address);
235 | dht.begin();
236 | lcd.begin(16, 2);
237 |
238 | // Start job
239 | do_send(&sendjob);
240 | }
241 |
242 | void loop() {
243 | os_runloop_once();
244 | }
245 |
246 | void prepareData() {
247 | //DHT
248 | delay(2000);
249 | float h = dht.readHumidity();
250 | float t = dht.readTemperature();
251 |
252 | if (isnan(h) || isnan(t)) {
253 | Serial.println("Failed to read from DHT sensor!");
254 | return;
255 | }
256 |
257 | //light
258 | float lightLux = 0;
259 | if(BH1750_Read(BH1750_address)==2){
260 | lightLux=((buff[0]<<8)|buff[1])/1.2;
261 | }
262 | char radiopacket[20];
263 |
264 | char str_t[6];
265 | dtostrf(t, 4, 1, str_t);
266 |
267 | char str_h[6];
268 | dtostrf(h, 4, 1, str_h);
269 |
270 | char str_l[6];
271 | dtostrf(lightLux, 5, 1, str_l);
272 |
273 | sprintf(radiopacket, "%s,%s,%s", str_t, str_h, str_l);
274 |
275 | memcpy(mydata, radiopacket, 20);
276 |
277 | lcd.setCursor(0, 1);
278 | lcd.print(str_t);
279 | lcd.print(" ");
280 | lcd.print(str_h);
281 | lcd.print(" ");
282 | lcd.print(str_l);
283 |
284 | mydata[19] = 0;
285 |
286 | }
287 |
288 | void BH1750_Init(int address){
289 |
290 | Wire.beginTransmission(address);
291 | Wire.write(0x10); // 1 [lux] aufloesung
292 | Wire.endTransmission();
293 | }
294 |
295 | byte BH1750_Read(int address){
296 |
297 | byte i=0;
298 | Wire.beginTransmission(address);
299 | Wire.requestFrom(address, 2);
300 | while(Wire.available()){
301 | buff[i] = Wire.read();
302 | i++;
303 | }
304 | Wire.endTransmission();
305 | return i;
306 | }
307 |
308 |
309 | #if 0
310 | char *dtostrf (double val, signed char width, unsigned char prec, char *sout) {
311 | char fmt[20];
312 | sprintf(fmt, "%%%d.%df", width, prec);
313 | sprintf(sout, fmt, val);
314 | return sout;
315 | }
316 | #else
317 | #include
318 | #include
319 | char *dtostrf(double val, int width, unsigned int prec, char *sout)
320 | {
321 | int decpt, sign, reqd, pad;
322 | const char *s, *e;
323 | char *p;
324 | s = fcvt(val, prec, &decpt, &sign);
325 | if (prec == 0 && decpt == 0) {
326 | s = (*s < '5') ? "0" : "1";
327 | reqd = 1;
328 | } else {
329 | reqd = strlen(s);
330 | if (reqd > decpt) reqd++;
331 | if (decpt == 0) reqd++;
332 | }
333 | if (sign) reqd++;
334 | p = sout;
335 | e = p + reqd;
336 | pad = width - reqd;
337 | if (pad > 0) {
338 | e += pad;
339 | while (pad-- > 0) *p++ = ' ';
340 | }
341 | if (sign) *p++ = '-';
342 | if (decpt <= 0 && prec > 0) {
343 | *p++ = '0';
344 | *p++ = '.';
345 | e++;
346 | while ( decpt < 0 ) {
347 | decpt++;
348 | *p++ = '0';
349 | }
350 | }
351 | while (p < e) {
352 | *p++ = *s++;
353 | if (p == e) break;
354 | if (--decpt == 0) *p++ = '.';
355 | }
356 | if (width < 0) {
357 | pad = (reqd + width) * -1;
358 | while (pad-- > 0) *p++ = ' ';
359 | }
360 | *p = 0;
361 | return sout;
362 | }
363 | #endif
364 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SenseTecnic/tutorial-samples/99a6d45b1150e802c511c277764ae7eda9aaa670/ttn-feather-m0/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/Adafruit_Unified_Sensor/README.md:
--------------------------------------------------------------------------------
1 | # Adafruit Unified Sensor Driver #
2 |
3 | Many small embedded systems exist to collect data from sensors, analyse the data, and either take an appropriate action or send that sensor data to another system for processing.
4 |
5 | One of the many challenges of embedded systems design is the fact that parts you used today may be out of production tomorrow, or system requirements may change and you may need to choose a different sensor down the road.
6 |
7 | Creating new drivers is a relatively easy task, but integrating them into existing systems is both error prone and time consuming since sensors rarely use the exact same units of measurement.
8 |
9 | By reducing all data to a single **sensors\_event\_t** 'type' and settling on specific, **standardised SI units** for each sensor family the same sensor types return values that are comparable with any other similar sensor. This enables you to switch sensor models with very little impact on the rest of the system, which can help mitigate some of the risks and problems of sensor availability and code reuse.
10 |
11 | The unified sensor abstraction layer is also useful for data-logging and data-transmission since you only have one well-known type to log or transmit over the air or wire.
12 |
13 | ## Unified Sensor Drivers ##
14 |
15 | The following drivers are based on the Adafruit Unified Sensor Driver:
16 |
17 | **Accelerometers**
18 | - [Adafruit\_ADXL345](https://github.com/adafruit/Adafruit_ADXL345)
19 | - [Adafruit\_LSM303DLHC](https://github.com/adafruit/Adafruit_LSM303DLHC)
20 | - [Adafruit\_MMA8451\_Library](https://github.com/adafruit/Adafruit_MMA8451_Library)
21 |
22 | **Gyroscope**
23 | - [Adafruit\_L3GD20\_U](https://github.com/adafruit/Adafruit_L3GD20_U)
24 |
25 | **Light**
26 | - [Adafruit\_TSL2561](https://github.com/adafruit/Adafruit_TSL2561)
27 | - [Adafruit\_TSL2591\_Library](https://github.com/adafruit/Adafruit_TSL2591_Library)
28 |
29 | **Magnetometers**
30 | - [Adafruit\_LSM303DLHC](https://github.com/adafruit/Adafruit_LSM303DLHC)
31 | - [Adafruit\_HMC5883\_Unified](https://github.com/adafruit/Adafruit_HMC5883_Unified)
32 |
33 | **Barometric Pressure**
34 | - [Adafruit\_BMP085\_Unified](https://github.com/adafruit/Adafruit_BMP085_Unified)
35 | - [Adafruit\_BMP183\_Unified\_Library](https://github.com/adafruit/Adafruit_BMP183_Unified_Library)
36 |
37 | **Humidity & Temperature**
38 | - [Adafruit\_DHT\_Unified](https://github.com/adafruit/Adafruit_DHT_Unified)
39 |
40 | ## How Does it Work? ##
41 |
42 | Any driver that supports the Adafruit unified sensor abstraction layer will implement the Adafruit\_Sensor base class. There are two main typedefs and one enum defined in Adafruit_Sensor.h that are used to 'abstract' away the sensor details and values:
43 |
44 | **Sensor Types (sensors\_type\_t)**
45 |
46 | These pre-defined sensor types are used to properly handle the two related typedefs below, and allows us determine what types of units the sensor uses, etc.
47 |
48 | ```
49 | /** Sensor types */
50 | typedef enum
51 | {
52 | SENSOR_TYPE_ACCELEROMETER = (1),
53 | SENSOR_TYPE_MAGNETIC_FIELD = (2),
54 | SENSOR_TYPE_ORIENTATION = (3),
55 | SENSOR_TYPE_GYROSCOPE = (4),
56 | SENSOR_TYPE_LIGHT = (5),
57 | SENSOR_TYPE_PRESSURE = (6),
58 | SENSOR_TYPE_PROXIMITY = (8),
59 | SENSOR_TYPE_GRAVITY = (9),
60 | SENSOR_TYPE_LINEAR_ACCELERATION = (10),
61 | SENSOR_TYPE_ROTATION_VECTOR = (11),
62 | SENSOR_TYPE_RELATIVE_HUMIDITY = (12),
63 | SENSOR_TYPE_AMBIENT_TEMPERATURE = (13),
64 | SENSOR_TYPE_VOLTAGE = (15),
65 | SENSOR_TYPE_CURRENT = (16),
66 | SENSOR_TYPE_COLOR = (17)
67 | } sensors_type_t;
68 | ```
69 |
70 | **Sensor Details (sensor\_t)**
71 |
72 | This typedef describes the specific capabilities of this sensor, and allows us to know what sensor we are using beneath the abstraction layer.
73 |
74 | ```
75 | /* Sensor details (40 bytes) */
76 | /** struct sensor_s is used to describe basic information about a specific sensor. */
77 | typedef struct
78 | {
79 | char name[12];
80 | int32_t version;
81 | int32_t sensor_id;
82 | int32_t type;
83 | float max_value;
84 | float min_value;
85 | float resolution;
86 | int32_t min_delay;
87 | } sensor_t;
88 | ```
89 |
90 | The individual fields are intended to be used as follows:
91 |
92 | - **name**: The sensor name or ID, up to a maximum of twelve characters (ex. "MPL115A2")
93 | - **version**: The version of the sensor HW and the driver to allow us to differentiate versions of the board or driver
94 | - **sensor\_id**: A unique sensor identifier that is used to differentiate this specific sensor instance from any others that are present on the system or in the sensor network
95 | - **type**: The sensor type, based on **sensors\_type\_t** in sensors.h
96 | - **max\_value**: The maximum value that this sensor can return (in the appropriate SI unit)
97 | - **min\_value**: The minimum value that this sensor can return (in the appropriate SI unit)
98 | - **resolution**: The smallest difference between two values that this sensor can report (in the appropriate SI unit)
99 | - **min\_delay**: The minimum delay in microseconds between two sensor events, or '0' if there is no constant sensor rate
100 |
101 | **Sensor Data/Events (sensors\_event\_t)**
102 |
103 | This typedef is used to return sensor data from any sensor supported by the abstraction layer, using standard SI units and scales.
104 |
105 | ```
106 | /* Sensor event (36 bytes) */
107 | /** struct sensor_event_s is used to provide a single sensor event in a common format. */
108 | typedef struct
109 | {
110 | int32_t version;
111 | int32_t sensor_id;
112 | int32_t type;
113 | int32_t reserved0;
114 | int32_t timestamp;
115 | union
116 | {
117 | float data[4];
118 | sensors_vec_t acceleration;
119 | sensors_vec_t magnetic;
120 | sensors_vec_t orientation;
121 | sensors_vec_t gyro;
122 | float temperature;
123 | float distance;
124 | float light;
125 | float pressure;
126 | float relative_humidity;
127 | float current;
128 | float voltage;
129 | sensors_color_t color;
130 | };
131 | } sensors_event_t;
132 | ```
133 | It includes the following fields:
134 |
135 | - **version**: Contain 'sizeof(sensors\_event\_t)' to identify which version of the API we're using in case this changes in the future
136 | - **sensor\_id**: A unique sensor identifier that is used to differentiate this specific sensor instance from any others that are present on the system or in the sensor network (must match the sensor\_id value in the corresponding sensor\_t enum above!)
137 | - **type**: the sensor type, based on **sensors\_type\_t** in sensors.h
138 | - **timestamp**: time in milliseconds when the sensor value was read
139 | - **data[4]**: An array of four 32-bit values that allows us to encapsulate any type of sensor data via a simple union (further described below)
140 |
141 | **Required Functions**
142 |
143 | In addition to the two standard types and the sensor type enum, all drivers based on Adafruit_Sensor must also implement the following two functions:
144 |
145 | ```
146 | bool getEvent(sensors_event_t*);
147 | ```
148 | Calling this function will populate the supplied sensors\_event\_t reference with the latest available sensor data. You should call this function as often as you want to update your data.
149 |
150 | ```
151 | void getSensor(sensor_t*);
152 | ```
153 | Calling this function will provide some basic information about the sensor (the sensor name, driver version, min and max values, etc.
154 |
155 | **Standardised SI values for sensors\_event\_t**
156 |
157 | A key part of the abstraction layer is the standardisation of values on SI units of a particular scale, which is accomplished via the data[4] union in sensors\_event\_t above. This 16 byte union includes fields for each main sensor type, and uses the following SI units and scales:
158 |
159 | - **acceleration**: values are in **meter per second per second** (m/s^2)
160 | - **magnetic**: values are in **micro-Tesla** (uT)
161 | - **orientation**: values are in **degrees**
162 | - **gyro**: values are in **rad/s**
163 | - **temperature**: values in **degrees centigrade** (Celsius)
164 | - **distance**: values are in **centimeters**
165 | - **light**: values are in **SI lux** units
166 | - **pressure**: values are in **hectopascal** (hPa)
167 | - **relative\_humidity**: values are in **percent**
168 | - **current**: values are in **milliamps** (mA)
169 | - **voltage**: values are in **volts** (V)
170 | - **color**: values are in 0..1.0 RGB channel luminosity and 32-bit RGBA format
171 |
172 | ## The Unified Driver Abstraction Layer in Practice ##
173 |
174 | Using the unified sensor abstraction layer is relatively easy once a compliant driver has been created.
175 |
176 | Every compliant sensor can now be read using a single, well-known 'type' (sensors\_event\_t), and there is a standardised way of interrogating a sensor about its specific capabilities (via sensor\_t).
177 |
178 | An example of reading the [TSL2561](https://github.com/adafruit/Adafruit_TSL2561) light sensor can be seen below:
179 |
180 | ```
181 | Adafruit_TSL2561 tsl = Adafruit_TSL2561(TSL2561_ADDR_FLOAT, 12345);
182 | ...
183 | /* Get a new sensor event */
184 | sensors_event_t event;
185 | tsl.getEvent(&event);
186 |
187 | /* Display the results (light is measured in lux) */
188 | if (event.light)
189 | {
190 | Serial.print(event.light); Serial.println(" lux");
191 | }
192 | else
193 | {
194 | /* If event.light = 0 lux the sensor is probably saturated
195 | and no reliable data could be generated! */
196 | Serial.println("Sensor overload");
197 | }
198 | ```
199 |
200 | Similarly, we can get the basic technical capabilities of this sensor with the following code:
201 |
202 | ```
203 | sensor_t sensor;
204 |
205 | sensor_t sensor;
206 | tsl.getSensor(&sensor);
207 |
208 | /* Display the sensor details */
209 | Serial.println("------------------------------------");
210 | Serial.print ("Sensor: "); Serial.println(sensor.name);
211 | Serial.print ("Driver Ver: "); Serial.println(sensor.version);
212 | Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
213 | Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" lux");
214 | Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" lux");
215 | Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" lux");
216 | Serial.println("------------------------------------");
217 | Serial.println("");
218 | ```
219 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/Adafruit_Unified_Sensor/library.properties:
--------------------------------------------------------------------------------
1 | name=Adafruit Unified Sensor
2 | version=1.0.2
3 | author=Adafruit
4 | maintainer=Adafruit
5 | sentence=Required for all Adafruit Unified Sensor based libraries.
6 | paragraph=A unified sensor abstraction layer used by many Adafruit sensor libraries.
7 | category=Sensors
8 | url=https://github.com/adafruit/Adafruit_Sensor
9 | architectures=*
10 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/DHT-sensor-library/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Thank you for opening an issue on an Adafruit Arduino library repository. To
2 | improve the speed of resolution please review the following guidelines and
3 | common troubleshooting steps below before creating the issue:
4 |
5 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
6 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why
7 | something isn't working as expected. In many cases the problem is a common issue
8 | that you will more quickly receive help from the forum community. GitHub issues
9 | are meant for known defects in the code. If you don't know if there is a defect
10 | in the code then start with troubleshooting on the forum first.
11 |
12 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully
13 | check all of the steps and commands to run have been followed. Consult the
14 | forum if you're unsure or have questions about steps in a guide/tutorial.
15 |
16 | - **For Arduino projects check these very common issues to ensure they don't apply**:
17 |
18 | - For uploading sketches or communicating with the board make sure you're using
19 | a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
20 | very hard to tell the difference between a data and charge cable! Try using the
21 | cable with other devices or swapping to another cable to confirm it is not
22 | the problem.
23 |
24 | - **Be sure you are supplying adequate power to the board.** Check the specs of
25 | your board and plug in an external power supply. In many cases just
26 | plugging a board into your computer is not enough to power it and other
27 | peripherals.
28 |
29 | - **Double check all soldering joints and connections.** Flakey connections
30 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
31 |
32 | - **Ensure you are using an official Arduino or Adafruit board.** We can't
33 | guarantee a clone board will have the same functionality and work as expected
34 | with this code and don't support them.
35 |
36 | If you're sure this issue is a defect in the code and checked the steps above
37 | please fill in the following fields to provide enough troubleshooting information.
38 | You may delete the guideline and text above to just leave the following details:
39 |
40 | - Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
41 |
42 | - Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
43 | VERSION HERE**
44 |
45 | - List the steps to reproduce the problem below (if possible attach a sketch or
46 | copy the sketch code in too): **LIST REPRO STEPS BELOW**
47 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/DHT-sensor-library/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code!
2 | Before you open the request please review the following guidelines and tips to
3 | help it be more easily integrated:
4 |
5 | - **Describe the scope of your change--i.e. what the change does and what parts
6 | of the code were modified.** This will help us understand any risks of integrating
7 | the code.
8 |
9 | - **Describe any known limitations with your change.** For example if the change
10 | doesn't apply to a supported platform of the library please mention it.
11 |
12 | - **Please run any tests or examples that can exercise your modified code.** We
13 | strive to not break users of the code and running tests/examples helps with this
14 | process.
15 |
16 | Thank you again for contributing! We will try to test and integrate the change
17 | as soon as we can, but be aware we have many GitHub repositories to manage and
18 | can't immediately respond to every request. There is no need to bump or check in
19 | on a pull request (it will clutter the discussion of the request).
20 |
21 | Also don't be worried if the request is closed or not integrated--sometimes the
22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the
23 | priorities of the pull request. Don't fret, the open source community thrives on
24 | forks and GitHub makes it easy to keep your changes in a forked repo.
25 |
26 | After reviewing the guidelines above you can delete this text from the pull request.
27 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/DHT-sensor-library/DHT.cpp:
--------------------------------------------------------------------------------
1 | /* DHT library
2 |
3 | MIT license
4 | written by Adafruit Industries
5 | */
6 |
7 | #include "DHT.h"
8 |
9 | #define MIN_INTERVAL 2000
10 |
11 | DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) {
12 | _pin = pin;
13 | _type = type;
14 | #ifdef __AVR
15 | _bit = digitalPinToBitMask(pin);
16 | _port = digitalPinToPort(pin);
17 | #endif
18 | _maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for
19 | // reading pulses from DHT sensor.
20 | // Note that count is now ignored as the DHT reading algorithm adjusts itself
21 | // basd on the speed of the processor.
22 | }
23 |
24 | void DHT::begin(void) {
25 | // set up the pins!
26 | pinMode(_pin, INPUT_PULLUP);
27 | // Using this value makes sure that millis() - lastreadtime will be
28 | // >= MIN_INTERVAL right away. Note that this assignment wraps around,
29 | // but so will the subtraction.
30 | _lastreadtime = -MIN_INTERVAL;
31 | DEBUG_PRINT("Max clock cycles: "); DEBUG_PRINTLN(_maxcycles, DEC);
32 | }
33 |
34 | //boolean S == Scale. True == Fahrenheit; False == Celcius
35 | float DHT::readTemperature(bool S, bool force) {
36 | float f = NAN;
37 |
38 | if (read(force)) {
39 | switch (_type) {
40 | case DHT11:
41 | f = data[2];
42 | if(S) {
43 | f = convertCtoF(f);
44 | }
45 | break;
46 | case DHT22:
47 | case DHT21:
48 | f = data[2] & 0x7F;
49 | f *= 256;
50 | f += data[3];
51 | f *= 0.1;
52 | if (data[2] & 0x80) {
53 | f *= -1;
54 | }
55 | if(S) {
56 | f = convertCtoF(f);
57 | }
58 | break;
59 | }
60 | }
61 | return f;
62 | }
63 |
64 | float DHT::convertCtoF(float c) {
65 | return c * 1.8 + 32;
66 | }
67 |
68 | float DHT::convertFtoC(float f) {
69 | return (f - 32) * 0.55555;
70 | }
71 |
72 | float DHT::readHumidity(bool force) {
73 | float f = NAN;
74 | if (read()) {
75 | switch (_type) {
76 | case DHT11:
77 | f = data[0];
78 | break;
79 | case DHT22:
80 | case DHT21:
81 | f = data[0];
82 | f *= 256;
83 | f += data[1];
84 | f *= 0.1;
85 | break;
86 | }
87 | }
88 | return f;
89 | }
90 |
91 | //boolean isFahrenheit: True == Fahrenheit; False == Celcius
92 | float DHT::computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit) {
93 | // Using both Rothfusz and Steadman's equations
94 | // http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml
95 | float hi;
96 |
97 | if (!isFahrenheit)
98 | temperature = convertCtoF(temperature);
99 |
100 | hi = 0.5 * (temperature + 61.0 + ((temperature - 68.0) * 1.2) + (percentHumidity * 0.094));
101 |
102 | if (hi > 79) {
103 | hi = -42.379 +
104 | 2.04901523 * temperature +
105 | 10.14333127 * percentHumidity +
106 | -0.22475541 * temperature*percentHumidity +
107 | -0.00683783 * pow(temperature, 2) +
108 | -0.05481717 * pow(percentHumidity, 2) +
109 | 0.00122874 * pow(temperature, 2) * percentHumidity +
110 | 0.00085282 * temperature*pow(percentHumidity, 2) +
111 | -0.00000199 * pow(temperature, 2) * pow(percentHumidity, 2);
112 |
113 | if((percentHumidity < 13) && (temperature >= 80.0) && (temperature <= 112.0))
114 | hi -= ((13.0 - percentHumidity) * 0.25) * sqrt((17.0 - abs(temperature - 95.0)) * 0.05882);
115 |
116 | else if((percentHumidity > 85.0) && (temperature >= 80.0) && (temperature <= 87.0))
117 | hi += ((percentHumidity - 85.0) * 0.1) * ((87.0 - temperature) * 0.2);
118 | }
119 |
120 | return isFahrenheit ? hi : convertFtoC(hi);
121 | }
122 |
123 | boolean DHT::read(bool force) {
124 | // Check if sensor was read less than two seconds ago and return early
125 | // to use last reading.
126 | uint32_t currenttime = millis();
127 | if (!force && ((currenttime - _lastreadtime) < 2000)) {
128 | return _lastresult; // return last correct measurement
129 | }
130 | _lastreadtime = currenttime;
131 |
132 | // Reset 40 bits of received data to zero.
133 | data[0] = data[1] = data[2] = data[3] = data[4] = 0;
134 |
135 | // Send start signal. See DHT datasheet for full signal diagram:
136 | // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf
137 |
138 | // Go into high impedence state to let pull-up raise data line level and
139 | // start the reading process.
140 | digitalWrite(_pin, HIGH);
141 | delay(250);
142 |
143 | // First set data line low for 20 milliseconds.
144 | pinMode(_pin, OUTPUT);
145 | digitalWrite(_pin, LOW);
146 | delay(20);
147 |
148 | uint32_t cycles[80];
149 | {
150 | // Turn off interrupts temporarily because the next sections are timing critical
151 | // and we don't want any interruptions.
152 | InterruptLock lock;
153 |
154 | // End the start signal by setting data line high for 40 microseconds.
155 | digitalWrite(_pin, HIGH);
156 | delayMicroseconds(40);
157 |
158 | // Now start reading the data line to get the value from the DHT sensor.
159 | pinMode(_pin, INPUT_PULLUP);
160 | delayMicroseconds(10); // Delay a bit to let sensor pull data line low.
161 |
162 | // First expect a low signal for ~80 microseconds followed by a high signal
163 | // for ~80 microseconds again.
164 | if (expectPulse(LOW) == 0) {
165 | DEBUG_PRINTLN(F("Timeout waiting for start signal low pulse."));
166 | _lastresult = false;
167 | return _lastresult;
168 | }
169 | if (expectPulse(HIGH) == 0) {
170 | DEBUG_PRINTLN(F("Timeout waiting for start signal high pulse."));
171 | _lastresult = false;
172 | return _lastresult;
173 | }
174 |
175 | // Now read the 40 bits sent by the sensor. Each bit is sent as a 50
176 | // microsecond low pulse followed by a variable length high pulse. If the
177 | // high pulse is ~28 microseconds then it's a 0 and if it's ~70 microseconds
178 | // then it's a 1. We measure the cycle count of the initial 50us low pulse
179 | // and use that to compare to the cycle count of the high pulse to determine
180 | // if the bit is a 0 (high state cycle count < low state cycle count), or a
181 | // 1 (high state cycle count > low state cycle count). Note that for speed all
182 | // the pulses are read into a array and then examined in a later step.
183 | for (int i=0; i<80; i+=2) {
184 | cycles[i] = expectPulse(LOW);
185 | cycles[i+1] = expectPulse(HIGH);
186 | }
187 | } // Timing critical code is now complete.
188 |
189 | // Inspect pulses and determine which ones are 0 (high state cycle count < low
190 | // state cycle count), or 1 (high state cycle count > low state cycle count).
191 | for (int i=0; i<40; ++i) {
192 | uint32_t lowCycles = cycles[2*i];
193 | uint32_t highCycles = cycles[2*i+1];
194 | if ((lowCycles == 0) || (highCycles == 0)) {
195 | DEBUG_PRINTLN(F("Timeout waiting for pulse."));
196 | _lastresult = false;
197 | return _lastresult;
198 | }
199 | data[i/8] <<= 1;
200 | // Now compare the low and high cycle times to see if the bit is a 0 or 1.
201 | if (highCycles > lowCycles) {
202 | // High cycles are greater than 50us low cycle count, must be a 1.
203 | data[i/8] |= 1;
204 | }
205 | // Else high cycles are less than (or equal to, a weird case) the 50us low
206 | // cycle count so this must be a zero. Nothing needs to be changed in the
207 | // stored data.
208 | }
209 |
210 | DEBUG_PRINTLN(F("Received:"));
211 | DEBUG_PRINT(data[0], HEX); DEBUG_PRINT(F(", "));
212 | DEBUG_PRINT(data[1], HEX); DEBUG_PRINT(F(", "));
213 | DEBUG_PRINT(data[2], HEX); DEBUG_PRINT(F(", "));
214 | DEBUG_PRINT(data[3], HEX); DEBUG_PRINT(F(", "));
215 | DEBUG_PRINT(data[4], HEX); DEBUG_PRINT(F(" =? "));
216 | DEBUG_PRINTLN((data[0] + data[1] + data[2] + data[3]) & 0xFF, HEX);
217 |
218 | // Check we read 40 bits and that the checksum matches.
219 | if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) {
220 | _lastresult = true;
221 | return _lastresult;
222 | }
223 | else {
224 | DEBUG_PRINTLN(F("Checksum failure!"));
225 | _lastresult = false;
226 | return _lastresult;
227 | }
228 | }
229 |
230 | // Expect the signal line to be at the specified level for a period of time and
231 | // return a count of loop cycles spent at that level (this cycle count can be
232 | // used to compare the relative time of two pulses). If more than a millisecond
233 | // ellapses without the level changing then the call fails with a 0 response.
234 | // This is adapted from Arduino's pulseInLong function (which is only available
235 | // in the very latest IDE versions):
236 | // https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_pulse.c
237 | uint32_t DHT::expectPulse(bool level) {
238 | uint32_t count = 0;
239 | // On AVR platforms use direct GPIO port access as it's much faster and better
240 | // for catching pulses that are 10's of microseconds in length:
241 | #ifdef __AVR
242 | uint8_t portState = level ? _bit : 0;
243 | while ((*portInputRegister(_port) & _bit) == portState) {
244 | if (count++ >= _maxcycles) {
245 | return 0; // Exceeded timeout, fail.
246 | }
247 | }
248 | // Otherwise fall back to using digitalRead (this seems to be necessary on ESP8266
249 | // right now, perhaps bugs in direct port access functions?).
250 | #else
251 | while (digitalRead(_pin) == level) {
252 | if (count++ >= _maxcycles) {
253 | return 0; // Exceeded timeout, fail.
254 | }
255 | }
256 | #endif
257 |
258 | return count;
259 | }
260 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/DHT-sensor-library/DHT.h:
--------------------------------------------------------------------------------
1 | /* DHT library
2 |
3 | MIT license
4 | written by Adafruit Industries
5 | */
6 | #ifndef DHT_H
7 | #define DHT_H
8 |
9 | #if ARDUINO >= 100
10 | #include "Arduino.h"
11 | #else
12 | #include "WProgram.h"
13 | #endif
14 |
15 |
16 | // Uncomment to enable printing out nice debug messages.
17 | //#define DHT_DEBUG
18 |
19 | // Define where debug output will be printed.
20 | #define DEBUG_PRINTER Serial
21 |
22 | // Setup debug printing macros.
23 | #ifdef DHT_DEBUG
24 | #define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); }
25 | #define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); }
26 | #else
27 | #define DEBUG_PRINT(...) {}
28 | #define DEBUG_PRINTLN(...) {}
29 | #endif
30 |
31 | // Define types of sensors.
32 | #define DHT11 11
33 | #define DHT22 22
34 | #define DHT21 21
35 | #define AM2301 21
36 |
37 |
38 | class DHT {
39 | public:
40 | DHT(uint8_t pin, uint8_t type, uint8_t count=6);
41 | void begin(void);
42 | float readTemperature(bool S=false, bool force=false);
43 | float convertCtoF(float);
44 | float convertFtoC(float);
45 | float computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit=true);
46 | float readHumidity(bool force=false);
47 | boolean read(bool force=false);
48 |
49 | private:
50 | uint8_t data[5];
51 | uint8_t _pin, _type;
52 | #ifdef __AVR
53 | // Use direct GPIO access on an 8-bit AVR so keep track of the port and bitmask
54 | // for the digital pin connected to the DHT. Other platforms will use digitalRead.
55 | uint8_t _bit, _port;
56 | #endif
57 | uint32_t _lastreadtime, _maxcycles;
58 | bool _lastresult;
59 |
60 | uint32_t expectPulse(bool level);
61 |
62 | };
63 |
64 | class InterruptLock {
65 | public:
66 | InterruptLock() {
67 | noInterrupts();
68 | }
69 | ~InterruptLock() {
70 | interrupts();
71 | }
72 |
73 | };
74 |
75 | #endif
76 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/DHT-sensor-library/DHT_U.cpp:
--------------------------------------------------------------------------------
1 | // DHT Temperature & Humidity Unified Sensor Library
2 | // Copyright (c) 2014 Adafruit Industries
3 | // Author: Tony DiCola
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 | #include "DHT_U.h"
23 |
24 | DHT_Unified::DHT_Unified(uint8_t pin, uint8_t type, uint8_t count, int32_t tempSensorId, int32_t humiditySensorId):
25 | _dht(pin, type, count),
26 | _type(type),
27 | _temp(this, tempSensorId),
28 | _humidity(this, humiditySensorId)
29 | {}
30 |
31 | void DHT_Unified::begin() {
32 | _dht.begin();
33 | }
34 |
35 | void DHT_Unified::setName(sensor_t* sensor) {
36 | switch(_type) {
37 | case DHT11:
38 | strncpy(sensor->name, "DHT11", sizeof(sensor->name) - 1);
39 | break;
40 | case DHT21:
41 | strncpy(sensor->name, "DHT21", sizeof(sensor->name) - 1);
42 | break;
43 | case DHT22:
44 | strncpy(sensor->name, "DHT22", sizeof(sensor->name) - 1);
45 | break;
46 | default:
47 | // TODO: Perhaps this should be an error? However main DHT library doesn't enforce
48 | // restrictions on the sensor type value. Pick a generic name for now.
49 | strncpy(sensor->name, "DHT?", sizeof(sensor->name) - 1);
50 | break;
51 | }
52 | sensor->name[sizeof(sensor->name)- 1] = 0;
53 | }
54 |
55 | void DHT_Unified::setMinDelay(sensor_t* sensor) {
56 | switch(_type) {
57 | case DHT11:
58 | sensor->min_delay = 1000000L; // 1 second (in microseconds)
59 | break;
60 | case DHT21:
61 | sensor->min_delay = 2000000L; // 2 seconds (in microseconds)
62 | break;
63 | case DHT22:
64 | sensor->min_delay = 2000000L; // 2 seconds (in microseconds)
65 | break;
66 | default:
67 | // Default to slowest sample rate in case of unknown type.
68 | sensor->min_delay = 2000000L; // 2 seconds (in microseconds)
69 | break;
70 | }
71 | }
72 |
73 | DHT_Unified::Temperature::Temperature(DHT_Unified* parent, int32_t id):
74 | _parent(parent),
75 | _id(id)
76 | {}
77 |
78 | bool DHT_Unified::Temperature::getEvent(sensors_event_t* event) {
79 | // Clear event definition.
80 | memset(event, 0, sizeof(sensors_event_t));
81 | // Populate sensor reading values.
82 | event->version = sizeof(sensors_event_t);
83 | event->sensor_id = _id;
84 | event->type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
85 | event->timestamp = millis();
86 | event->temperature = _parent->_dht.readTemperature();
87 |
88 | return true;
89 | }
90 |
91 | void DHT_Unified::Temperature::getSensor(sensor_t* sensor) {
92 | // Clear sensor definition.
93 | memset(sensor, 0, sizeof(sensor_t));
94 | // Set sensor name.
95 | _parent->setName(sensor);
96 | // Set version and ID
97 | sensor->version = DHT_SENSOR_VERSION;
98 | sensor->sensor_id = _id;
99 | // Set type and characteristics.
100 | sensor->type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
101 | _parent->setMinDelay(sensor);
102 | switch (_parent->_type) {
103 | case DHT11:
104 | sensor->max_value = 50.0F;
105 | sensor->min_value = 0.0F;
106 | sensor->resolution = 2.0F;
107 | break;
108 | case DHT21:
109 | sensor->max_value = 80.0F;
110 | sensor->min_value = -40.0F;
111 | sensor->resolution = 0.1F;
112 | break;
113 | case DHT22:
114 | sensor->max_value = 125.0F;
115 | sensor->min_value = -40.0F;
116 | sensor->resolution = 0.1F;
117 | break;
118 | default:
119 | // Unknown type, default to 0.
120 | sensor->max_value = 0.0F;
121 | sensor->min_value = 0.0F;
122 | sensor->resolution = 0.0F;
123 | break;
124 | }
125 | }
126 |
127 | DHT_Unified::Humidity::Humidity(DHT_Unified* parent, int32_t id):
128 | _parent(parent),
129 | _id(id)
130 | {}
131 |
132 | bool DHT_Unified::Humidity::getEvent(sensors_event_t* event) {
133 | // Clear event definition.
134 | memset(event, 0, sizeof(sensors_event_t));
135 | // Populate sensor reading values.
136 | event->version = sizeof(sensors_event_t);
137 | event->sensor_id = _id;
138 | event->type = SENSOR_TYPE_RELATIVE_HUMIDITY;
139 | event->timestamp = millis();
140 | event->relative_humidity = _parent->_dht.readHumidity();
141 |
142 | return true;
143 | }
144 |
145 | void DHT_Unified::Humidity::getSensor(sensor_t* sensor) {
146 | // Clear sensor definition.
147 | memset(sensor, 0, sizeof(sensor_t));
148 | // Set sensor name.
149 | _parent->setName(sensor);
150 | // Set version and ID
151 | sensor->version = DHT_SENSOR_VERSION;
152 | sensor->sensor_id = _id;
153 | // Set type and characteristics.
154 | sensor->type = SENSOR_TYPE_RELATIVE_HUMIDITY;
155 | _parent->setMinDelay(sensor);
156 | switch (_parent->_type) {
157 | case DHT11:
158 | sensor->max_value = 80.0F;
159 | sensor->min_value = 20.0F;
160 | sensor->resolution = 5.0F;
161 | break;
162 | case DHT21:
163 | sensor->max_value = 100.0F;
164 | sensor->min_value = 0.0F;
165 | sensor->resolution = 0.1F;
166 | break;
167 | case DHT22:
168 | sensor->max_value = 100.0F;
169 | sensor->min_value = 0.0F;
170 | sensor->resolution = 0.1F;
171 | break;
172 | default:
173 | // Unknown type, default to 0.
174 | sensor->max_value = 0.0F;
175 | sensor->min_value = 0.0F;
176 | sensor->resolution = 0.0F;
177 | break;
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/DHT-sensor-library/DHT_U.h:
--------------------------------------------------------------------------------
1 | // DHT Temperature & Humidity Unified Sensor Library
2 | // Copyright (c) 2014 Adafruit Industries
3 | // Author: Tony DiCola
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 | #ifndef DHT_U_H
23 | #define DHT_U_H
24 |
25 | #include
26 | #include
27 |
28 | #define DHT_SENSOR_VERSION 1
29 |
30 | class DHT_Unified {
31 | public:
32 | DHT_Unified(uint8_t pin, uint8_t type, uint8_t count=6, int32_t tempSensorId=-1, int32_t humiditySensorId=-1);
33 | void begin();
34 |
35 | class Temperature : public Adafruit_Sensor {
36 | public:
37 | Temperature(DHT_Unified* parent, int32_t id);
38 | bool getEvent(sensors_event_t* event);
39 | void getSensor(sensor_t* sensor);
40 |
41 | private:
42 | DHT_Unified* _parent;
43 | int32_t _id;
44 |
45 | };
46 |
47 | class Humidity : public Adafruit_Sensor {
48 | public:
49 | Humidity(DHT_Unified* parent, int32_t id);
50 | bool getEvent(sensors_event_t* event);
51 | void getSensor(sensor_t* sensor);
52 |
53 | private:
54 | DHT_Unified* _parent;
55 | int32_t _id;
56 |
57 | };
58 |
59 | Temperature temperature() {
60 | return _temp;
61 | }
62 |
63 | Humidity humidity() {
64 | return _humidity;
65 | }
66 |
67 | private:
68 | DHT _dht;
69 | uint8_t _type;
70 | Temperature _temp;
71 | Humidity _humidity;
72 |
73 | void setName(sensor_t* sensor);
74 | void setMinDelay(sensor_t* sensor);
75 |
76 | };
77 |
78 | #endif
79 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/DHT-sensor-library/README.md:
--------------------------------------------------------------------------------
1 | This is an Arduino library for the DHT series of low cost temperature/humidity sensors.
2 |
3 | Tutorial: https://learn.adafruit.com/dht
4 |
5 | To download. click the DOWNLOADS button in the top right corner, rename the uncompressed folder DHT. Check that the DHT folder contains DHT.cpp and DHT.h. Place the DHT library folder your /libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE.
6 |
7 | # Adafruit DHT Humidity & Temperature Unified Sensor Library
8 |
9 | This library also includes an optional class for the
10 | [DHT humidity and temperature sensor](https://learn.adafruit.com/dht/overview)
11 | which is designed to work with the [Adafruit unified sensor library](https://learn.adafruit.com/using-the-adafruit-unified-sensor-driver/introduction).
12 |
13 | You must have the following Arduino libraries installed to use this class:
14 |
15 | - [Adafruit Unified Sensor Library](https://github.com/adafruit/Adafruit_Sensor)
16 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/DHT-sensor-library/examples/DHT_Unified_Sensor/DHT_Unified_Sensor.ino:
--------------------------------------------------------------------------------
1 | // DHT Temperature & Humidity Sensor
2 | // Unified Sensor Library Example
3 | // Written by Tony DiCola for Adafruit Industries
4 | // Released under an MIT license.
5 |
6 | // Depends on the following Arduino libraries:
7 | // - Adafruit Unified Sensor Library: https://github.com/adafruit/Adafruit_Sensor
8 | // - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
9 |
10 | #include
11 | #include
12 | #include
13 |
14 | #define DHTPIN 2 // Pin which is connected to the DHT sensor.
15 |
16 | // Uncomment the type of sensor in use:
17 | //#define DHTTYPE DHT11 // DHT 11
18 | #define DHTTYPE DHT22 // DHT 22 (AM2302)
19 | //#define DHTTYPE DHT21 // DHT 21 (AM2301)
20 |
21 | // See guide for details on sensor wiring and usage:
22 | // https://learn.adafruit.com/dht/overview
23 |
24 | DHT_Unified dht(DHTPIN, DHTTYPE);
25 |
26 | uint32_t delayMS;
27 |
28 | void setup() {
29 | Serial.begin(9600);
30 | // Initialize device.
31 | dht.begin();
32 | Serial.println("DHTxx Unified Sensor Example");
33 | // Print temperature sensor details.
34 | sensor_t sensor;
35 | dht.temperature().getSensor(&sensor);
36 | Serial.println("------------------------------------");
37 | Serial.println("Temperature");
38 | Serial.print ("Sensor: "); Serial.println(sensor.name);
39 | Serial.print ("Driver Ver: "); Serial.println(sensor.version);
40 | Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
41 | Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" *C");
42 | Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" *C");
43 | Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" *C");
44 | Serial.println("------------------------------------");
45 | // Print humidity sensor details.
46 | dht.humidity().getSensor(&sensor);
47 | Serial.println("------------------------------------");
48 | Serial.println("Humidity");
49 | Serial.print ("Sensor: "); Serial.println(sensor.name);
50 | Serial.print ("Driver Ver: "); Serial.println(sensor.version);
51 | Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
52 | Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println("%");
53 | Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println("%");
54 | Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println("%");
55 | Serial.println("------------------------------------");
56 | // Set delay between sensor readings based on sensor details.
57 | delayMS = sensor.min_delay / 1000;
58 | }
59 |
60 | void loop() {
61 | // Delay between measurements.
62 | delay(delayMS);
63 | // Get temperature event and print its value.
64 | sensors_event_t event;
65 | dht.temperature().getEvent(&event);
66 | if (isnan(event.temperature)) {
67 | Serial.println("Error reading temperature!");
68 | }
69 | else {
70 | Serial.print("Temperature: ");
71 | Serial.print(event.temperature);
72 | Serial.println(" *C");
73 | }
74 | // Get humidity event and print its value.
75 | dht.humidity().getEvent(&event);
76 | if (isnan(event.relative_humidity)) {
77 | Serial.println("Error reading humidity!");
78 | }
79 | else {
80 | Serial.print("Humidity: ");
81 | Serial.print(event.relative_humidity);
82 | Serial.println("%");
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/DHT-sensor-library/examples/DHTtester/DHTtester.ino:
--------------------------------------------------------------------------------
1 | // Example testing sketch for various DHT humidity/temperature sensors
2 | // Written by ladyada, public domain
3 |
4 | #include "DHT.h"
5 |
6 | #define DHTPIN 2 // what digital pin we're connected to
7 |
8 | // Uncomment whatever type you're using!
9 | //#define DHTTYPE DHT11 // DHT 11
10 | #define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
11 | //#define DHTTYPE DHT21 // DHT 21 (AM2301)
12 |
13 | // Connect pin 1 (on the left) of the sensor to +5V
14 | // NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
15 | // to 3.3V instead of 5V!
16 | // Connect pin 2 of the sensor to whatever your DHTPIN is
17 | // Connect pin 4 (on the right) of the sensor to GROUND
18 | // Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor
19 |
20 | // Initialize DHT sensor.
21 | // Note that older versions of this library took an optional third parameter to
22 | // tweak the timings for faster processors. This parameter is no longer needed
23 | // as the current DHT reading algorithm adjusts itself to work on faster procs.
24 | DHT dht(DHTPIN, DHTTYPE);
25 |
26 | void setup() {
27 | Serial.begin(9600);
28 | Serial.println("DHTxx test!");
29 |
30 | dht.begin();
31 | }
32 |
33 | void loop() {
34 | // Wait a few seconds between measurements.
35 | delay(2000);
36 |
37 | // Reading temperature or humidity takes about 250 milliseconds!
38 | // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
39 | float h = dht.readHumidity();
40 | // Read temperature as Celsius (the default)
41 | float t = dht.readTemperature();
42 | // Read temperature as Fahrenheit (isFahrenheit = true)
43 | float f = dht.readTemperature(true);
44 |
45 | // Check if any reads failed and exit early (to try again).
46 | if (isnan(h) || isnan(t) || isnan(f)) {
47 | Serial.println("Failed to read from DHT sensor!");
48 | return;
49 | }
50 |
51 | // Compute heat index in Fahrenheit (the default)
52 | float hif = dht.computeHeatIndex(f, h);
53 | // Compute heat index in Celsius (isFahreheit = false)
54 | float hic = dht.computeHeatIndex(t, h, false);
55 |
56 | Serial.print("Humidity: ");
57 | Serial.print(h);
58 | Serial.print(" %\t");
59 | Serial.print("Temperature: ");
60 | Serial.print(t);
61 | Serial.print(" *C ");
62 | Serial.print(f);
63 | Serial.print(" *F\t");
64 | Serial.print("Heat index: ");
65 | Serial.print(hic);
66 | Serial.print(" *C ");
67 | Serial.print(hif);
68 | Serial.println(" *F");
69 | }
70 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/DHT-sensor-library/keywords.txt:
--------------------------------------------------------------------------------
1 | ###########################################
2 | # Syntax Coloring Map For DHT-sensor-library
3 | ###########################################
4 |
5 | ###########################################
6 | # Datatypes (KEYWORD1)
7 | ###########################################
8 |
9 | DHT KEYWORD1
10 |
11 | ###########################################
12 | # Methods and Functions (KEYWORD2)
13 | ###########################################
14 |
15 | begin KEYWORD2
16 | readTemperature KEYWORD2
17 | convertCtoF KEYWORD2
18 | convertFtoC KEYWORD2
19 | computeHeatIndex KEYWORD2
20 | readHumidity KEYWORD2
21 | read KEYWORD2
22 |
23 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/DHT-sensor-library/library.properties:
--------------------------------------------------------------------------------
1 | name=DHT sensor library
2 | version=1.3.0
3 | author=Adafruit
4 | maintainer=Adafruit
5 | sentence=Arduino library for DHT11, DHT22, etc Temp & Humidity Sensors
6 | paragraph=Arduino library for DHT11, DHT22, etc Temp & Humidity Sensors
7 | category=Sensors
8 | url=https://github.com/adafruit/DHT-sensor-library
9 | architectures=*
10 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/doc/LMiC-v1.5.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SenseTecnic/tutorial-samples/99a6d45b1150e802c511c277764ae7eda9aaa670/ttn-feather-m0/libraries/arduino-lmic-master/doc/LMiC-v1.5.pdf
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/doc/README.txt:
--------------------------------------------------------------------------------
1 | DISCLAIMER:
2 | Please note that the software is provided AS IS and we cannot
3 | provide support for optimizations, adaptations, integration,
4 | ports to other platforms or device drivers!
5 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/doc/release-notes.txt:
--------------------------------------------------------------------------------
1 | ==============================================================================
2 | LMIC VERSION 1.4 (17-Mar-2015)
3 | -------------------------------
4 |
5 | - changed API: inverted port indicator flag in LMIC.txrxFlags
6 | (now TXRX_PORT, previously TXRX_NOPORT)
7 |
8 | - fixed offset OFF_CFLIST constant
9 |
10 | - changed CRC-16 algorithm for beacons to CCITT(XMODEM) polynomial
11 |
12 | - fixed radio driver (low data rate optimization for SF11+SF12 only for BW125)
13 |
14 | - fixed timer rollover handling in job queue
15 |
16 | ==============================================================================
17 | LMIC VERSION 1.5 (8-May-2015)
18 | ------------------------------
19 |
20 | - fixed condition in convFreq()
21 |
22 | - fixed freq*100 bug and freq==0 bug for CFList
23 |
24 | - fixed TX scheduling bug
25 |
26 | - better support for GNU compiler toolchain
27 |
28 | ==============================================================================
29 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/examples/raw/raw.ino:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2015 Matthijs Kooijman
3 | *
4 | * Permission is hereby granted, free of charge, to anyone
5 | * obtaining a copy of this document and accompanying files,
6 | * to do whatever they want with them without any restriction,
7 | * including, but not limited to, copying, modification and redistribution.
8 | * NO WARRANTY OF ANY KIND IS PROVIDED.
9 | *
10 | * This example transmits data on hardcoded channel and receives data
11 | * when not transmitting. Running this sketch on two nodes should allow
12 | * them to communicate.
13 | *******************************************************************************/
14 |
15 | #include
16 | #include
17 | #include
18 |
19 | #if !defined(DISABLE_INVERT_IQ_ON_RX)
20 | #error This example requires DISABLE_INVERT_IQ_ON_RX to be set. Update \
21 | config.h in the lmic library to set it.
22 | #endif
23 |
24 | // How often to send a packet. Note that this sketch bypasses the normal
25 | // LMIC duty cycle limiting, so when you change anything in this sketch
26 | // (payload length, frequency, spreading factor), be sure to check if
27 | // this interval should not also be increased.
28 | // See this spreadsheet for an easy airtime and duty cycle calculator:
29 | // https://docs.google.com/spreadsheets/d/1voGAtQAjC1qBmaVuP1ApNKs1ekgUjavHuVQIXyYSvNc
30 | #define TX_INTERVAL 2000
31 |
32 | // Pin mapping
33 | const lmic_pinmap lmic_pins = {
34 | .nss = 6,
35 | .rxtx = LMIC_UNUSED_PIN,
36 | .rst = 5,
37 | .dio = {2, 3, 4},
38 | };
39 |
40 |
41 | // These callbacks are only used in over-the-air activation, so they are
42 | // left empty here (we cannot leave them out completely unless
43 | // DISABLE_JOIN is set in config.h, otherwise the linker will complain).
44 | void os_getArtEui (u1_t* buf) { }
45 | void os_getDevEui (u1_t* buf) { }
46 | void os_getDevKey (u1_t* buf) { }
47 |
48 | void onEvent (ev_t ev) {
49 | }
50 |
51 | osjob_t txjob;
52 | osjob_t timeoutjob;
53 | static void tx_func (osjob_t* job);
54 |
55 | // Transmit the given string and call the given function afterwards
56 | void tx(const char *str, osjobcb_t func) {
57 | os_radio(RADIO_RST); // Stop RX first
58 | delay(1); // Wait a bit, without this os_radio below asserts, apparently because the state hasn't changed yet
59 | LMIC.dataLen = 0;
60 | while (*str)
61 | LMIC.frame[LMIC.dataLen++] = *str++;
62 | LMIC.osjob.func = func;
63 | os_radio(RADIO_TX);
64 | Serial.println("TX");
65 | }
66 |
67 | // Enable rx mode and call func when a packet is received
68 | void rx(osjobcb_t func) {
69 | LMIC.osjob.func = func;
70 | LMIC.rxtime = os_getTime(); // RX _now_
71 | // Enable "continuous" RX (e.g. without a timeout, still stops after
72 | // receiving a packet)
73 | os_radio(RADIO_RXON);
74 | Serial.println("RX");
75 | }
76 |
77 | static void rxtimeout_func(osjob_t *job) {
78 | digitalWrite(LED_BUILTIN, LOW); // off
79 | }
80 |
81 | static void rx_func (osjob_t* job) {
82 | // Blink once to confirm reception and then keep the led on
83 | digitalWrite(LED_BUILTIN, LOW); // off
84 | delay(10);
85 | digitalWrite(LED_BUILTIN, HIGH); // on
86 |
87 | // Timeout RX (i.e. update led status) after 3 periods without RX
88 | os_setTimedCallback(&timeoutjob, os_getTime() + ms2osticks(3*TX_INTERVAL), rxtimeout_func);
89 |
90 | // Reschedule TX so that it should not collide with the other side's
91 | // next TX
92 | os_setTimedCallback(&txjob, os_getTime() + ms2osticks(TX_INTERVAL/2), tx_func);
93 |
94 | Serial.print("Got ");
95 | Serial.print(LMIC.dataLen);
96 | Serial.println(" bytes");
97 | Serial.write(LMIC.frame, LMIC.dataLen);
98 | Serial.println();
99 |
100 | // Restart RX
101 | rx(rx_func);
102 | }
103 |
104 | static void txdone_func (osjob_t* job) {
105 | rx(rx_func);
106 | }
107 |
108 | // log text to USART and toggle LED
109 | static void tx_func (osjob_t* job) {
110 | // say hello
111 | tx("Hello, world!", txdone_func);
112 | // reschedule job every TX_INTERVAL (plus a bit of random to prevent
113 | // systematic collisions), unless packets are received, then rx_func
114 | // will reschedule at half this time.
115 | os_setTimedCallback(job, os_getTime() + ms2osticks(TX_INTERVAL + random(500)), tx_func);
116 | }
117 |
118 | // application entry point
119 | void setup() {
120 | Serial.begin(115200);
121 | Serial.println("Starting");
122 | #ifdef VCC_ENABLE
123 | // For Pinoccio Scout boards
124 | pinMode(VCC_ENABLE, OUTPUT);
125 | digitalWrite(VCC_ENABLE, HIGH);
126 | delay(1000);
127 | #endif
128 |
129 | pinMode(LED_BUILTIN, OUTPUT);
130 |
131 | // initialize runtime env
132 | os_init();
133 |
134 | // Set up these settings once, and use them for both TX and RX
135 |
136 | #if defined(CFG_eu868)
137 | // Use a frequency in the g3 which allows 10% duty cycling.
138 | LMIC.freq = 869525000;
139 | #elif defined(CFG_us915)
140 | LMIC.freq = 902300000;
141 | #endif
142 |
143 | // Maximum TX power
144 | LMIC.txpow = 27;
145 | // Use a medium spread factor. This can be increased up to SF12 for
146 | // better range, but then the interval should be (significantly)
147 | // lowered to comply with duty cycle limits as well.
148 | LMIC.datarate = DR_SF9;
149 | // This sets CR 4/5, BW125 (except for DR_SF7B, which uses BW250)
150 | LMIC.rps = updr2rps(LMIC.datarate);
151 |
152 | Serial.println("Started");
153 | Serial.flush();
154 |
155 | // setup initial job
156 | os_setCallback(&txjob, tx_func);
157 | }
158 |
159 | void loop() {
160 | // execute scheduled jobs and events
161 | os_runloop_once();
162 | }
163 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/examples/ttn-abp/ttn-abp.ino:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman
3 | *
4 | * Permission is hereby granted, free of charge, to anyone
5 | * obtaining a copy of this document and accompanying files,
6 | * to do whatever they want with them without any restriction,
7 | * including, but not limited to, copying, modification and redistribution.
8 | * NO WARRANTY OF ANY KIND IS PROVIDED.
9 | *
10 | * This example sends a valid LoRaWAN packet with payload "Hello,
11 | * world!", using frequency and encryption settings matching those of
12 | * the The Things Network.
13 | *
14 | * This uses ABP (Activation-by-personalisation), where a DevAddr and
15 | * Session keys are preconfigured (unlike OTAA, where a DevEUI and
16 | * application key is configured, while the DevAddr and session keys are
17 | * assigned/generated in the over-the-air-activation procedure).
18 | *
19 | * Note: LoRaWAN per sub-band duty-cycle limitation is enforced (1% in
20 | * g1, 0.1% in g2), but not the TTN fair usage policy (which is probably
21 | * violated by this sketch when left running for longer)!
22 | *
23 | * To use this sketch, first register your application and device with
24 | * the things network, to set or generate a DevAddr, NwkSKey and
25 | * AppSKey. Each device should have their own unique values for these
26 | * fields.
27 | *
28 | * Do not forget to define the radio type correctly in config.h.
29 | *
30 | *******************************************************************************/
31 |
32 | #include
33 | #include
34 | #include
35 |
36 | // LoRaWAN NwkSKey, network session key
37 | // This is the default Semtech key, which is used by the early prototype TTN
38 | // network.
39 | static const PROGMEM u1_t NWKSKEY[16] = { 0x1D, 0x13, 0xD8, 0xDE, 0x60, 0xAD, 0x4A, 0x59, 0x5B, 0x5F, 0xEB, 0x2B, 0xC9, 0x7F, 0xEA, 0x5F };
40 |
41 | // LoRaWAN AppSKey, application session key
42 | // This is the default Semtech key, which is used by the early prototype TTN
43 | // network.
44 | static const u1_t PROGMEM APPSKEY[16] = { 0xE1, 0x6A, 0x67, 0xFD, 0x89, 0x97, 0x0C, 0xEA, 0x44, 0xD5, 0x88, 0x48, 0x79, 0x03, 0x9B, 0xE9 };
45 |
46 | // LoRaWAN end-device address (DevAddr)
47 | static const u4_t DEVADDR = 0x260212B3 ; // <-- Change this address for every node!
48 |
49 | // These callbacks are only used in over-the-air activation, so they are
50 | // left empty here (we cannot leave them out completely unless
51 | // DISABLE_JOIN is set in config.h, otherwise the linker will complain).
52 | void os_getArtEui (u1_t* buf) { }
53 | void os_getDevEui (u1_t* buf) { }
54 | void os_getDevKey (u1_t* buf) { }
55 |
56 | static uint8_t mydata[] = "Hello, world!";
57 | static osjob_t sendjob;
58 |
59 | // Schedule TX every this many seconds (might become longer due to duty
60 | // cycle limitations).
61 | const unsigned TX_INTERVAL = 60;
62 |
63 | // Pin mapping
64 | const lmic_pinmap lmic_pins = {
65 |
66 | .nss = 8, // Internal connected
67 | //.rxen = 0, // Not used for RFM92/RFM95
68 | //.txen = 0, // Not used for RFM92/RFM95
69 | .rxtx = LMIC_UNUSED_PIN,
70 | .rst = 4, // Internal connected
71 | .dio = {3, 5, 6}, // Connect "i01" to "5"
72 | // Connect "D2" to "6"
73 | };
74 |
75 | void onEvent (ev_t ev) {
76 | Serial.print(os_getTime());
77 | Serial.print(": ");
78 | switch(ev) {
79 | case EV_SCAN_TIMEOUT:
80 | Serial.println(F("EV_SCAN_TIMEOUT"));
81 | break;
82 | case EV_BEACON_FOUND:
83 | Serial.println(F("EV_BEACON_FOUND"));
84 | break;
85 | case EV_BEACON_MISSED:
86 | Serial.println(F("EV_BEACON_MISSED"));
87 | break;
88 | case EV_BEACON_TRACKED:
89 | Serial.println(F("EV_BEACON_TRACKED"));
90 | break;
91 | case EV_JOINING:
92 | Serial.println(F("EV_JOINING"));
93 | break;
94 | case EV_JOINED:
95 | Serial.println(F("EV_JOINED"));
96 | break;
97 | case EV_RFU1:
98 | Serial.println(F("EV_RFU1"));
99 | break;
100 | case EV_JOIN_FAILED:
101 | Serial.println(F("EV_JOIN_FAILED"));
102 | break;
103 | case EV_REJOIN_FAILED:
104 | Serial.println(F("EV_REJOIN_FAILED"));
105 | break;
106 | case EV_TXCOMPLETE:
107 | Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
108 | if (LMIC.txrxFlags & TXRX_ACK)
109 | Serial.println(F("Received ack"));
110 | if (LMIC.dataLen) {
111 | Serial.println(F("Received "));
112 | Serial.println(LMIC.dataLen);
113 | Serial.println(F(" bytes of payload"));
114 | }
115 | // Schedule next transmission
116 | os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
117 | break;
118 | case EV_LOST_TSYNC:
119 | Serial.println(F("EV_LOST_TSYNC"));
120 | break;
121 | case EV_RESET:
122 | Serial.println(F("EV_RESET"));
123 | break;
124 | case EV_RXCOMPLETE:
125 | // data received in ping slot
126 | Serial.println(F("EV_RXCOMPLETE"));
127 | break;
128 | case EV_LINK_DEAD:
129 | Serial.println(F("EV_LINK_DEAD"));
130 | break;
131 | case EV_LINK_ALIVE:
132 | Serial.println(F("EV_LINK_ALIVE"));
133 | break;
134 | default:
135 | Serial.println(F("Unknown event"));
136 | break;
137 | }
138 | }
139 |
140 | void do_send(osjob_t* j){
141 | // Check if there is not a current TX/RX job running
142 | if (LMIC.opmode & OP_TXRXPEND) {
143 | Serial.println(F("OP_TXRXPEND, not sending"));
144 | } else {
145 | // Prepare upstream data transmission at the next possible time.
146 | LMIC_setTxData2(1, mydata, sizeof(mydata)-1, 0);
147 | Serial.println(F("Packet queued"));
148 | }
149 | // Next TX is scheduled after TX_COMPLETE event.
150 | }
151 |
152 | void setup() {
153 | Serial.begin(115200);
154 | Serial.println(F("Starting"));
155 |
156 | #ifdef VCC_ENABLE
157 | // For Pinoccio Scout boards
158 | pinMode(VCC_ENABLE, OUTPUT);
159 | digitalWrite(VCC_ENABLE, HIGH);
160 | delay(1000);
161 | #endif
162 |
163 | // LMIC init
164 | os_init();
165 | // Reset the MAC state. Session and pending data transfers will be discarded.
166 | LMIC_reset();
167 |
168 | // Set static session parameters. Instead of dynamically establishing a session
169 | // by joining the network, precomputed session parameters are be provided.
170 | #ifdef PROGMEM
171 | // On AVR, these values are stored in flash and only copied to RAM
172 | // once. Copy them to a temporary buffer here, LMIC_setSession will
173 | // copy them into a buffer of its own again.
174 | uint8_t appskey[sizeof(APPSKEY)];
175 | uint8_t nwkskey[sizeof(NWKSKEY)];
176 | memcpy_P(appskey, APPSKEY, sizeof(APPSKEY));
177 | memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY));
178 | LMIC_setSession (0x1, DEVADDR, nwkskey, appskey);
179 | #else
180 | // If not running an AVR with PROGMEM, just use the arrays directly
181 | LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY);
182 | #endif
183 |
184 | #if defined(CFG_eu868)
185 | // Set up the channels used by the Things Network, which corresponds
186 | // to the defaults of most gateways. Without this, only three base
187 | // channels from the LoRaWAN specification are used, which certainly
188 | // works, so it is good for debugging, but can overload those
189 | // frequencies, so be sure to configure the full frequency range of
190 | // your network here (unless your network autoconfigures them).
191 | // Setting up channels should happen after LMIC_setSession, as that
192 | // configures the minimal channel set.
193 | // NA-US channels 0-71 are configured automatically
194 | LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
195 | LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI); // g-band
196 | LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
197 | LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
198 | LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
199 | LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
200 | LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
201 | LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
202 | LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK, DR_FSK), BAND_MILLI); // g2-band
203 | // TTN defines an additional channel at 869.525Mhz using SF9 for class B
204 | // devices' ping slots. LMIC does not have an easy way to define set this
205 | // frequency and support for class B is spotty and untested, so this
206 | // frequency is not configured here.
207 | #elif defined(CFG_us915)
208 | // NA-US channels 0-71 are configured automatically
209 | // but only one group of 8 should (a subband) should be active
210 | // TTN recommends the second sub band, 1 in a zero based count.
211 | // https://github.com/TheThingsNetwork/gateway-conf/blob/master/US-global_conf.json
212 | LMIC_selectSubBand(1);
213 | #endif
214 |
215 | // Disable link check validation
216 | LMIC_setLinkCheckMode(0);
217 |
218 | // TTN uses SF9 for its RX2 window.
219 | LMIC.dn2Dr = DR_SF9;
220 |
221 | // Set data rate and transmit power for uplink (note: txpow seems to be ignored by the library)
222 | LMIC_setDrTxpow(DR_SF7,14);
223 |
224 | // Start job
225 | do_send(&sendjob);
226 | }
227 |
228 | void loop() {
229 | os_runloop_once();
230 | }
231 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/examples/ttn-otaa/ttn-otaa.ino:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman
3 | *
4 | * Permission is hereby granted, free of charge, to anyone
5 | * obtaining a copy of this document and accompanying files,
6 | * to do whatever they want with them without any restriction,
7 | * including, but not limited to, copying, modification and redistribution.
8 | * NO WARRANTY OF ANY KIND IS PROVIDED.
9 | *
10 | * This example sends a valid LoRaWAN packet with payload "Hello,
11 | * world!", using frequency and encryption settings matching those of
12 | * the The Things Network.
13 | *
14 | * This uses OTAA (Over-the-air activation), where where a DevEUI and
15 | * application key is configured, which are used in an over-the-air
16 | * activation procedure where a DevAddr and session keys are
17 | * assigned/generated for use with all further communication.
18 | *
19 | * Note: LoRaWAN per sub-band duty-cycle limitation is enforced (1% in
20 | * g1, 0.1% in g2), but not the TTN fair usage policy (which is probably
21 | * violated by this sketch when left running for longer)!
22 |
23 | * To use this sketch, first register your application and device with
24 | * the things network, to set or generate an AppEUI, DevEUI and AppKey.
25 | * Multiple devices can use the same AppEUI, but each device has its own
26 | * DevEUI and AppKey.
27 | *
28 | * Do not forget to define the radio type correctly in config.h.
29 | *
30 | *******************************************************************************/
31 |
32 | #include
33 | #include
34 | #include
35 |
36 | // This EUI must be in little-endian format, so least-significant-byte
37 | // first. When copying an EUI from ttnctl output, this means to reverse
38 | // the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,
39 | // 0x70.
40 | static const u1_t PROGMEM APPEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
41 | void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}
42 |
43 | // This should also be in little endian format, see above.
44 | static const u1_t PROGMEM DEVEUI[8]={ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
45 | void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}
46 |
47 | // This key should be in big endian format (or, since it is not really a
48 | // number but a block of memory, endianness does not really apply). In
49 | // practice, a key taken from ttnctl can be copied as-is.
50 | // The key shown here is the semtech default key.
51 | static const u1_t PROGMEM APPKEY[16] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C };
52 | void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}
53 |
54 | static uint8_t mydata[] = "Hello, world!";
55 | static osjob_t sendjob;
56 |
57 | // Schedule TX every this many seconds (might become longer due to duty
58 | // cycle limitations).
59 | const unsigned TX_INTERVAL = 60;
60 |
61 | // Pin mapping
62 | const lmic_pinmap lmic_pins = {
63 | .nss = 6,
64 | .rxtx = LMIC_UNUSED_PIN,
65 | .rst = 5,
66 | .dio = {2, 3, 4},
67 | };
68 |
69 | void onEvent (ev_t ev) {
70 | Serial.print(os_getTime());
71 | Serial.print(": ");
72 | switch(ev) {
73 | case EV_SCAN_TIMEOUT:
74 | Serial.println(F("EV_SCAN_TIMEOUT"));
75 | break;
76 | case EV_BEACON_FOUND:
77 | Serial.println(F("EV_BEACON_FOUND"));
78 | break;
79 | case EV_BEACON_MISSED:
80 | Serial.println(F("EV_BEACON_MISSED"));
81 | break;
82 | case EV_BEACON_TRACKED:
83 | Serial.println(F("EV_BEACON_TRACKED"));
84 | break;
85 | case EV_JOINING:
86 | Serial.println(F("EV_JOINING"));
87 | break;
88 | case EV_JOINED:
89 | Serial.println(F("EV_JOINED"));
90 |
91 | // Disable link check validation (automatically enabled
92 | // during join, but not supported by TTN at this time).
93 | LMIC_setLinkCheckMode(0);
94 | break;
95 | case EV_RFU1:
96 | Serial.println(F("EV_RFU1"));
97 | break;
98 | case EV_JOIN_FAILED:
99 | Serial.println(F("EV_JOIN_FAILED"));
100 | break;
101 | case EV_REJOIN_FAILED:
102 | Serial.println(F("EV_REJOIN_FAILED"));
103 | break;
104 | break;
105 | case EV_TXCOMPLETE:
106 | Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
107 | if (LMIC.txrxFlags & TXRX_ACK)
108 | Serial.println(F("Received ack"));
109 | if (LMIC.dataLen) {
110 | Serial.println(F("Received "));
111 | Serial.println(LMIC.dataLen);
112 | Serial.println(F(" bytes of payload"));
113 | }
114 | // Schedule next transmission
115 | os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
116 | break;
117 | case EV_LOST_TSYNC:
118 | Serial.println(F("EV_LOST_TSYNC"));
119 | break;
120 | case EV_RESET:
121 | Serial.println(F("EV_RESET"));
122 | break;
123 | case EV_RXCOMPLETE:
124 | // data received in ping slot
125 | Serial.println(F("EV_RXCOMPLETE"));
126 | break;
127 | case EV_LINK_DEAD:
128 | Serial.println(F("EV_LINK_DEAD"));
129 | break;
130 | case EV_LINK_ALIVE:
131 | Serial.println(F("EV_LINK_ALIVE"));
132 | break;
133 | default:
134 | Serial.println(F("Unknown event"));
135 | break;
136 | }
137 | }
138 |
139 | void do_send(osjob_t* j){
140 | // Check if there is not a current TX/RX job running
141 | if (LMIC.opmode & OP_TXRXPEND) {
142 | Serial.println(F("OP_TXRXPEND, not sending"));
143 | } else {
144 | // Prepare upstream data transmission at the next possible time.
145 | LMIC_setTxData2(1, mydata, sizeof(mydata)-1, 0);
146 | Serial.println(F("Packet queued"));
147 | }
148 | // Next TX is scheduled after TX_COMPLETE event.
149 | }
150 |
151 | void setup() {
152 | Serial.begin(9600);
153 | Serial.println(F("Starting"));
154 |
155 | #ifdef VCC_ENABLE
156 | // For Pinoccio Scout boards
157 | pinMode(VCC_ENABLE, OUTPUT);
158 | digitalWrite(VCC_ENABLE, HIGH);
159 | delay(1000);
160 | #endif
161 |
162 | // LMIC init
163 | os_init();
164 | // Reset the MAC state. Session and pending data transfers will be discarded.
165 | LMIC_reset();
166 |
167 | // Start job (sending automatically starts OTAA too)
168 | do_send(&sendjob);
169 | }
170 |
171 | void loop() {
172 | os_runloop_once();
173 | }
174 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/library.properties:
--------------------------------------------------------------------------------
1 | name=IBM LMIC framework
2 | version=1.5.0+arduino-1
3 | author=IBM
4 | maintainer=Matthijs Kooijman
5 | sentence=Arduino port of the LMIC (LoraWAN-in-C, formerly LoraMAC-in-C) framework provided by IBM.
6 | paragraph=Supports SX1272/SX1276 and HopeRF RFM92/RFM95 tranceivers
7 | category=Communication
8 | url=http://www.research.ibm.com/labs/zurich/ics/lrsc/lmic.html
9 | architectures=*
10 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/src/hal/hal.cpp:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2015 Matthijs Kooijman
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * This the HAL to run LMIC on top of the Arduino environment.
9 | *******************************************************************************/
10 |
11 | #include
12 | #include
13 | #include "../lmic.h"
14 | #include "hal.h"
15 | #include
16 |
17 | // -----------------------------------------------------------------------------
18 | // I/O
19 |
20 | void hal_interrupt_init(); // Fwd declaration
21 |
22 | static void hal_io_init () {
23 | // NSS and DIO0 are required, DIO1 is required for LoRa, DIO2 for FSK
24 | ASSERT(lmic_pins.nss != LMIC_UNUSED_PIN);
25 | ASSERT(lmic_pins.dio[0] != LMIC_UNUSED_PIN);
26 | ASSERT(lmic_pins.dio[1] != LMIC_UNUSED_PIN || lmic_pins.dio[2] != LMIC_UNUSED_PIN);
27 |
28 | pinMode(lmic_pins.nss, OUTPUT);
29 | if (lmic_pins.rxtx != LMIC_UNUSED_PIN)
30 | pinMode(lmic_pins.rxtx, OUTPUT);
31 | if (lmic_pins.rst != LMIC_UNUSED_PIN)
32 | pinMode(lmic_pins.rst, OUTPUT);
33 |
34 | hal_interrupt_init();
35 | }
36 |
37 | // val == 1 => tx 1
38 | void hal_pin_rxtx (u1_t val) {
39 | if (lmic_pins.rxtx != LMIC_UNUSED_PIN)
40 | digitalWrite(lmic_pins.rxtx, val);
41 | }
42 |
43 | // set radio RST pin to given value (or keep floating!)
44 | void hal_pin_rst (u1_t val) {
45 | if (lmic_pins.rst == LMIC_UNUSED_PIN)
46 | return;
47 |
48 | if(val == 0 || val == 1) { // drive pin
49 | pinMode(lmic_pins.rst, OUTPUT);
50 | digitalWrite(lmic_pins.rst, val);
51 | } else { // keep pin floating
52 | pinMode(lmic_pins.rst, INPUT);
53 | }
54 | }
55 |
56 | #if !defined(LMIC_USE_INTERRUPTS)
57 | static void hal_interrupt_init() {
58 | pinMode(lmic_pins.dio[0], INPUT);
59 | if (lmic_pins.dio[1] != LMIC_UNUSED_PIN)
60 | pinMode(lmic_pins.dio[1], INPUT);
61 | if (lmic_pins.dio[2] != LMIC_UNUSED_PIN)
62 | pinMode(lmic_pins.dio[2], INPUT);
63 | }
64 |
65 | static bool dio_states[NUM_DIO] = {0};
66 | static void hal_io_check() {
67 | uint8_t i;
68 | for (i = 0; i < NUM_DIO; ++i) {
69 | if (lmic_pins.dio[i] == LMIC_UNUSED_PIN)
70 | continue;
71 |
72 | if (dio_states[i] != digitalRead(lmic_pins.dio[i])) {
73 | dio_states[i] = !dio_states[i];
74 | if (dio_states[i])
75 | radio_irq_handler(i);
76 | }
77 | }
78 | }
79 |
80 | #else
81 | // Interrupt handlers
82 | static bool interrupt_flags[NUM_DIO] = {0};
83 |
84 | static void hal_isrPin0() {
85 | interrupt_flags[0] = true;
86 | }
87 | static void hal_isrPin1() {
88 | interrupt_flags[1] = true;
89 | }
90 | static void hal_isrPin2() {
91 | interrupt_flags[2] = true;
92 | }
93 |
94 | typedef void (*isr_t)();
95 | static isr_t interrupt_fns[NUM_DIO] = {hal_isrPin0, hal_isrPin1, hal_isrPin2};
96 |
97 | static void hal_interrupt_init() {
98 | for (uint8_t i = 0; i < NUM_DIO; ++i) {
99 | if (lmic_pins.dio[i] == LMIC_UNUSED_PIN)
100 | continue;
101 |
102 | attachInterrupt(digitalPinToInterrupt(lmic_pins.dio[i]), interrupt_fns[i], RISING);
103 | }
104 | }
105 |
106 | static void hal_io_check() {
107 | uint8_t i;
108 | for (i = 0; i < NUM_DIO; ++i) {
109 | if (lmic_pins.dio[i] == LMIC_UNUSED_PIN)
110 | continue;
111 |
112 | if (interrupt_flags[i]) {
113 | interrupt_flags[i] = false;
114 | radio_irq_handler(i);
115 | }
116 | }
117 | }
118 | #endif // LMIC_USE_INTERRUPTS
119 |
120 | // -----------------------------------------------------------------------------
121 | // SPI
122 |
123 | static const SPISettings settings(LMIC_SPI_FREQ, MSBFIRST, SPI_MODE0);
124 |
125 | static void hal_spi_init () {
126 | SPI.begin();
127 | }
128 |
129 | void hal_pin_nss (u1_t val) {
130 | if (!val)
131 | SPI.beginTransaction(settings);
132 | else
133 | SPI.endTransaction();
134 |
135 | //Serial.println(val?">>":"<<");
136 | digitalWrite(lmic_pins.nss, val);
137 | }
138 |
139 | // perform SPI transaction with radio
140 | u1_t hal_spi (u1_t out) {
141 | u1_t res = SPI.transfer(out);
142 | /*
143 | Serial.print(">");
144 | Serial.print(out, HEX);
145 | Serial.print("<");
146 | Serial.println(res, HEX);
147 | */
148 | return res;
149 | }
150 |
151 | // -----------------------------------------------------------------------------
152 | // TIME
153 |
154 | static void hal_time_init () {
155 | // Nothing to do
156 | }
157 |
158 | u4_t hal_ticks () {
159 | // Because micros() is scaled down in this function, micros() will
160 | // overflow before the tick timer should, causing the tick timer to
161 | // miss a significant part of its values if not corrected. To fix
162 | // this, the "overflow" serves as an overflow area for the micros()
163 | // counter. It consists of three parts:
164 | // - The US_PER_OSTICK upper bits are effectively an extension for
165 | // the micros() counter and are added to the result of this
166 | // function.
167 | // - The next bit overlaps with the most significant bit of
168 | // micros(). This is used to detect micros() overflows.
169 | // - The remaining bits are always zero.
170 | //
171 | // By comparing the overlapping bit with the corresponding bit in
172 | // the micros() return value, overflows can be detected and the
173 | // upper bits are incremented. This is done using some clever
174 | // bitwise operations, to remove the need for comparisons and a
175 | // jumps, which should result in efficient code. By avoiding shifts
176 | // other than by multiples of 8 as much as possible, this is also
177 | // efficient on AVR (which only has 1-bit shifts).
178 | static uint8_t overflow = 0;
179 |
180 | // Scaled down timestamp. The top US_PER_OSTICK_EXPONENT bits are 0,
181 | // the others will be the lower bits of our return value.
182 | uint32_t scaled = micros() >> US_PER_OSTICK_EXPONENT;
183 | // Most significant byte of scaled
184 | uint8_t msb = scaled >> 24;
185 | // Mask pointing to the overlapping bit in msb and overflow.
186 | const uint8_t mask = (1 << (7 - US_PER_OSTICK_EXPONENT));
187 | // Update overflow. If the overlapping bit is different
188 | // between overflow and msb, it is added to the stored value,
189 | // so the overlapping bit becomes equal again and, if it changed
190 | // from 1 to 0, the upper bits are incremented.
191 | overflow += (msb ^ overflow) & mask;
192 |
193 | // Return the scaled value with the upper bits of stored added. The
194 | // overlapping bit will be equal and the lower bits will be 0, so
195 | // bitwise or is a no-op for them.
196 | return scaled | ((uint32_t)overflow << 24);
197 |
198 | // 0 leads to correct, but overly complex code (it could just return
199 | // micros() unmodified), 8 leaves no room for the overlapping bit.
200 | static_assert(US_PER_OSTICK_EXPONENT > 0 && US_PER_OSTICK_EXPONENT < 8, "Invalid US_PER_OSTICK_EXPONENT value");
201 | }
202 |
203 | // Returns the number of ticks until time. Negative values indicate that
204 | // time has already passed.
205 | static s4_t delta_time(u4_t time) {
206 | return (s4_t)(time - hal_ticks());
207 | }
208 |
209 | void hal_waitUntil (u4_t time) {
210 | s4_t delta = delta_time(time);
211 | // From delayMicroseconds docs: Currently, the largest value that
212 | // will produce an accurate delay is 16383.
213 | while (delta > (16000 / US_PER_OSTICK)) {
214 | delay(16);
215 | delta -= (16000 / US_PER_OSTICK);
216 | }
217 | if (delta > 0)
218 | delayMicroseconds(delta * US_PER_OSTICK);
219 | }
220 |
221 | // check and rewind for target time
222 | u1_t hal_checkTimer (u4_t time) {
223 | // No need to schedule wakeup, since we're not sleeping
224 | return delta_time(time) <= 0;
225 | }
226 |
227 | static uint8_t irqlevel = 0;
228 |
229 | void hal_disableIRQs () {
230 | noInterrupts();
231 | irqlevel++;
232 | }
233 |
234 | void hal_enableIRQs () {
235 | if(--irqlevel == 0) {
236 | interrupts();
237 |
238 | // Instead of using proper interrupts (which are a bit tricky
239 | // and/or not available on all pins on AVR), just poll the pin
240 | // values. Since os_runloop disables and re-enables interrupts,
241 | // putting this here makes sure we check at least once every
242 | // loop.
243 | //
244 | // As an additional bonus, this prevents the can of worms that
245 | // we would otherwise get for running SPI transfers inside ISRs
246 | hal_io_check();
247 | }
248 | }
249 |
250 | void hal_sleep () {
251 | // Not implemented
252 | }
253 |
254 | // -----------------------------------------------------------------------------
255 |
256 | #if defined(LMIC_PRINTF_TO)
257 | static int uart_putchar (char c, FILE *)
258 | {
259 | LMIC_PRINTF_TO.write(c) ;
260 | return 0 ;
261 | }
262 |
263 | void hal_printf_init() {
264 | // create a FILE structure to reference our UART output function
265 | static FILE uartout;
266 | memset(&uartout, 0, sizeof(uartout));
267 |
268 | // fill in the UART file descriptor with pointer to writer.
269 | fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
270 |
271 | // The uart is the standard output device STDOUT.
272 | stdout = &uartout ;
273 | }
274 | #endif // defined(LMIC_PRINTF_TO)
275 |
276 | void hal_init () {
277 | // configure radio I/O and interrupt handler
278 | hal_io_init();
279 | // configure radio SPI
280 | hal_spi_init();
281 | // configure timer and interrupt handler
282 | hal_time_init();
283 | #if defined(LMIC_PRINTF_TO)
284 | // printf support
285 | hal_printf_init();
286 | #endif
287 | }
288 |
289 | void hal_failed (const char *file, u2_t line) {
290 | #if defined(LMIC_FAILURE_TO)
291 | LMIC_FAILURE_TO.println("FAILURE ");
292 | LMIC_FAILURE_TO.print(file);
293 | LMIC_FAILURE_TO.print(':');
294 | LMIC_FAILURE_TO.println(line);
295 | LMIC_FAILURE_TO.flush();
296 | #endif
297 | hal_disableIRQs();
298 | while(1);
299 | }
300 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/src/hal/hal.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2015 Matthijs Kooijman
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * This the HAL to run LMIC on top of the Arduino environment.
9 | *******************************************************************************/
10 | #ifndef _hal_hal_h_
11 | #define _hal_hal_h_
12 |
13 | static const int NUM_DIO = 3;
14 |
15 | struct lmic_pinmap {
16 | u1_t nss;
17 | u1_t rxtx;
18 | u1_t rst;
19 | u1_t dio[NUM_DIO];
20 | };
21 |
22 | // Use this for any unused pins.
23 | const u1_t LMIC_UNUSED_PIN = 0xff;
24 |
25 | // Declared here, to be defined an initialized by the application
26 | extern const lmic_pinmap lmic_pins;
27 |
28 | #endif // _hal_hal_h_
29 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/src/lmic.h:
--------------------------------------------------------------------------------
1 | #ifdef __cplusplus
2 | extern "C"{
3 | #endif
4 |
5 | #include "lmic/lmic.h"
6 |
7 | #ifdef __cplusplus
8 | }
9 | #endif
10 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/src/lmic/config.h:
--------------------------------------------------------------------------------
1 | #ifndef _lmic_config_h_
2 | #define _lmic_config_h_
3 |
4 | // In the original LMIC code, these config values were defined on the
5 | // gcc commandline. Since Arduino does not allow easily modifying the
6 | // compiler commandline, use this file instead.
7 |
8 | //#define CFG_eu868 1
9 | #define CFG_us915 1
10 | // This is the SX1272/SX1273 radio, which is also used on the HopeRF
11 | // RFM92 boards.
12 | //#define CFG_sx1272_radio 1
13 | // This is the SX1276/SX1277/SX1278/SX1279 radio, which is also used on
14 | // the HopeRF RFM95 boards.
15 | #define CFG_sx1276_radio 1
16 |
17 | // 16 μs per tick
18 | // LMIC requires ticks to be 15.5μs - 100 μs long
19 | #define US_PER_OSTICK_EXPONENT 4
20 | #define US_PER_OSTICK (1 << US_PER_OSTICK_EXPONENT)
21 | #define OSTICKS_PER_SEC (1000000 / US_PER_OSTICK)
22 |
23 | // Change the SPI clock speed if you encounter errors
24 | // communicating with the radio.
25 | // The standard range is 125kHz-8MHz, but some boards can go faster.
26 | #define LMIC_SPI_FREQ 1E6
27 |
28 | // Enable this to allow using printf() to print to the given serial port
29 | // (or any other Print object). This can be easy for debugging. The
30 | // current implementation only works on AVR, though.
31 | //#define LMIC_PRINTF_TO Serial
32 |
33 | // Enable this to use interrupt handler routines listening for RISING signals.
34 | // Otherwise, the library polls digital input lines for changes.
35 | //#define LMIC_USE_INTERRUPTS
36 |
37 | // Any runtime assertion failures are printed to this serial port (or
38 | // any other Print object). If this is unset, any failures just silently
39 | // halt execution.
40 | #define LMIC_FAILURE_TO Serial
41 |
42 | // Uncomment this to disable all code related to joining
43 | //#define DISABLE_JOIN
44 | // Uncomment this to disable all code related to ping
45 | //#define DISABLE_PING
46 | // Uncomment this to disable all code related to beacon tracking.
47 | // Requires ping to be disabled too
48 | //#define DISABLE_BEACONS
49 |
50 | // Uncomment these to disable the corresponding MAC commands.
51 | // Class A
52 | //#define DISABLE_MCMD_DCAP_REQ // duty cycle cap
53 | //#define DISABLE_MCMD_DN2P_SET // 2nd DN window param
54 | //#define DISABLE_MCMD_SNCH_REQ // set new channel
55 | // Class B
56 | //#define DISABLE_MCMD_PING_SET // set ping freq, automatically disabled by DISABLE_PING
57 | //#define DISABLE_MCMD_BCNI_ANS // next beacon start, automatical disabled by DISABLE_BEACON
58 |
59 | // In LoRaWAN, a gateway applies I/Q inversion on TX, and nodes do the
60 | // same on RX. This ensures that gateways can talk to nodes and vice
61 | // versa, but gateways will not hear other gateways and nodes will not
62 | // hear other nodes. By uncommenting this macro, this inversion is
63 | // disabled and this node can hear other nodes. If two nodes both have
64 | // this macro set, they can talk to each other (but they can no longer
65 | // hear gateways). This should probably only be used when debugging
66 | // and/or when talking to the radio directly (e.g. like in the "raw"
67 | // example).
68 | //#define DISABLE_INVERT_IQ_ON_RX
69 | #endif // _lmic_config_h_
70 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/src/lmic/hal.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #ifndef _hal_hpp_
13 | #define _hal_hpp_
14 |
15 | #ifdef __cplusplus
16 | extern "C"{
17 | #endif
18 |
19 | /*
20 | * initialize hardware (IO, SPI, TIMER, IRQ).
21 | */
22 | void hal_init (void);
23 |
24 | /*
25 | * drive radio NSS pin (0=low, 1=high).
26 | */
27 | void hal_pin_nss (u1_t val);
28 |
29 | /*
30 | * drive radio RX/TX pins (0=rx, 1=tx).
31 | */
32 | void hal_pin_rxtx (u1_t val);
33 |
34 | /*
35 | * control radio RST pin (0=low, 1=high, 2=floating)
36 | */
37 | void hal_pin_rst (u1_t val);
38 |
39 | /*
40 | * perform 8-bit SPI transaction with radio.
41 | * - write given byte 'outval'
42 | * - read byte and return value
43 | */
44 | u1_t hal_spi (u1_t outval);
45 |
46 | /*
47 | * disable all CPU interrupts.
48 | * - might be invoked nested
49 | * - will be followed by matching call to hal_enableIRQs()
50 | */
51 | void hal_disableIRQs (void);
52 |
53 | /*
54 | * enable CPU interrupts.
55 | */
56 | void hal_enableIRQs (void);
57 |
58 | /*
59 | * put system and CPU in low-power mode, sleep until interrupt.
60 | */
61 | void hal_sleep (void);
62 |
63 | /*
64 | * return 32-bit system time in ticks.
65 | */
66 | u4_t hal_ticks (void);
67 |
68 | /*
69 | * busy-wait until specified timestamp (in ticks) is reached.
70 | */
71 | void hal_waitUntil (u4_t time);
72 |
73 | /*
74 | * check and rewind timer for target time.
75 | * - return 1 if target time is close
76 | * - otherwise rewind timer for target time or full period and return 0
77 | */
78 | u1_t hal_checkTimer (u4_t targettime);
79 |
80 | /*
81 | * perform fatal failure action.
82 | * - called by assertions
83 | * - action could be HALT or reboot
84 | */
85 | void hal_failed (const char *file, u2_t line);
86 |
87 | #ifdef __cplusplus
88 | } // extern "C"
89 | #endif
90 |
91 | #endif // _hal_hpp_
92 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/src/lmic/lmic.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | //! @file
13 | //! @brief LMIC API
14 |
15 | #ifndef _lmic_h_
16 | #define _lmic_h_
17 |
18 | #include "oslmic.h"
19 | #include "lorabase.h"
20 |
21 | #ifdef __cplusplus
22 | extern "C"{
23 | #endif
24 |
25 | // LMIC version
26 | #define LMIC_VERSION_MAJOR 1
27 | #define LMIC_VERSION_MINOR 5
28 | #define LMIC_VERSION_BUILD 1431528305
29 |
30 | enum { MAX_FRAME_LEN = 64 }; //!< Library cap on max frame length
31 | enum { TXCONF_ATTEMPTS = 8 }; //!< Transmit attempts for confirmed frames
32 | enum { MAX_MISSED_BCNS = 20 }; // threshold for triggering rejoin requests
33 | enum { MAX_RXSYMS = 100 }; // stop tracking beacon beyond this
34 |
35 | enum { LINK_CHECK_CONT = 12 , // continue with this after reported dead link
36 | LINK_CHECK_DEAD = 24 , // after this UP frames and no response from NWK assume link is dead
37 | LINK_CHECK_INIT = -12 , // UP frame count until we inc datarate
38 | LINK_CHECK_OFF =-128 }; // link check disabled
39 |
40 | enum { TIME_RESYNC = 6*128 }; // secs
41 | enum { TXRX_GUARD_ms = 6000 }; // msecs - don't start TX-RX transaction before beacon
42 | enum { JOIN_GUARD_ms = 9000 }; // msecs - don't start Join Req/Acc transaction before beacon
43 | enum { TXRX_BCNEXT_secs = 2 }; // secs - earliest start after beacon time
44 | enum { RETRY_PERIOD_secs = 3 }; // secs - random period for retrying a confirmed send
45 |
46 | #if defined(CFG_eu868) // EU868 spectrum ====================================================
47 |
48 | enum { MAX_CHANNELS = 16 }; //!< Max supported channels
49 | enum { MAX_BANDS = 4 };
50 |
51 | enum { LIMIT_CHANNELS = (1<<4) }; // EU868 will never have more channels
52 | //! \internal
53 | struct band_t {
54 | u2_t txcap; // duty cycle limitation: 1/txcap
55 | s1_t txpow; // maximum TX power
56 | u1_t lastchnl; // last used channel
57 | ostime_t avail; // channel is blocked until this time
58 | };
59 | TYPEDEF_xref2band_t; //!< \internal
60 |
61 | #elif defined(CFG_us915) // US915 spectrum =================================================
62 |
63 | enum { MAX_XCHANNELS = 2 }; // extra channels in RAM, channels 0-71 are immutable
64 | enum { MAX_TXPOW_125kHz = 30 };
65 |
66 | #endif // ==========================================================================
67 |
68 | // Keep in sync with evdefs.hpp::drChange
69 | enum { DRCHG_SET, DRCHG_NOJACC, DRCHG_NOACK, DRCHG_NOADRACK, DRCHG_NWKCMD };
70 | enum { KEEP_TXPOW = -128 };
71 |
72 |
73 | #if !defined(DISABLE_PING)
74 | //! \internal
75 | struct rxsched_t {
76 | u1_t dr;
77 | u1_t intvExp; // 0..7
78 | u1_t slot; // runs from 0 to 128
79 | u1_t rxsyms;
80 | ostime_t rxbase;
81 | ostime_t rxtime; // start of next spot
82 | u4_t freq;
83 | };
84 | TYPEDEF_xref2rxsched_t; //!< \internal
85 | #endif // !DISABLE_PING
86 |
87 |
88 | #if !defined(DISABLE_BEACONS)
89 | //! Parsing and tracking states of beacons.
90 | enum { BCN_NONE = 0x00, //!< No beacon received
91 | BCN_PARTIAL = 0x01, //!< Only first (common) part could be decoded (info,lat,lon invalid/previous)
92 | BCN_FULL = 0x02, //!< Full beacon decoded
93 | BCN_NODRIFT = 0x04, //!< No drift value measured yet
94 | BCN_NODDIFF = 0x08 }; //!< No differential drift measured yet
95 | //! Information about the last and previous beacons.
96 | struct bcninfo_t {
97 | ostime_t txtime; //!< Time when the beacon was sent
98 | s1_t rssi; //!< Adjusted RSSI value of last received beacon
99 | s1_t snr; //!< Scaled SNR value of last received beacon
100 | u1_t flags; //!< Last beacon reception and tracking states. See BCN_* values.
101 | u4_t time; //!< GPS time in seconds of last beacon (received or surrogate)
102 | //
103 | u1_t info; //!< Info field of last beacon (valid only if BCN_FULL set)
104 | s4_t lat; //!< Lat field of last beacon (valid only if BCN_FULL set)
105 | s4_t lon; //!< Lon field of last beacon (valid only if BCN_FULL set)
106 | };
107 | #endif // !DISABLE_BEACONS
108 |
109 | // purpose of receive window - lmic_t.rxState
110 | enum { RADIO_RST=0, RADIO_TX=1, RADIO_RX=2, RADIO_RXON=3 };
111 | // Netid values / lmic_t.netid
112 | enum { NETID_NONE=(int)~0U, NETID_MASK=(int)0xFFFFFF };
113 | // MAC operation modes (lmic_t.opmode).
114 | enum { OP_NONE = 0x0000,
115 | OP_SCAN = 0x0001, // radio scan to find a beacon
116 | OP_TRACK = 0x0002, // track my networks beacon (netid)
117 | OP_JOINING = 0x0004, // device joining in progress (blocks other activities)
118 | OP_TXDATA = 0x0008, // TX user data (buffered in pendTxData)
119 | OP_POLL = 0x0010, // send empty UP frame to ACK confirmed DN/fetch more DN data
120 | OP_REJOIN = 0x0020, // occasionally send JOIN REQUEST
121 | OP_SHUTDOWN = 0x0040, // prevent MAC from doing anything
122 | OP_TXRXPEND = 0x0080, // TX/RX transaction pending
123 | OP_RNDTX = 0x0100, // prevent TX lining up after a beacon
124 | OP_PINGINI = 0x0200, // pingable is initialized and scheduling active
125 | OP_PINGABLE = 0x0400, // we're pingable
126 | OP_NEXTCHNL = 0x0800, // find a new channel
127 | OP_LINKDEAD = 0x1000, // link was reported as dead
128 | OP_TESTMODE = 0x2000, // developer test mode
129 | };
130 | // TX-RX transaction flags - report back to user
131 | enum { TXRX_ACK = 0x80, // confirmed UP frame was acked
132 | TXRX_NACK = 0x40, // confirmed UP frame was not acked
133 | TXRX_NOPORT = 0x20, // set if a frame with a port was RXed, clr if no frame/no port
134 | TXRX_PORT = 0x10, // set if a frame with a port was RXed, LMIC.frame[LMIC.dataBeg-1] => port
135 | TXRX_DNW1 = 0x01, // received in 1st DN slot
136 | TXRX_DNW2 = 0x02, // received in 2dn DN slot
137 | TXRX_PING = 0x04 }; // received in a scheduled RX slot
138 | // Event types for event callback
139 | enum _ev_t { EV_SCAN_TIMEOUT=1, EV_BEACON_FOUND,
140 | EV_BEACON_MISSED, EV_BEACON_TRACKED, EV_JOINING,
141 | EV_JOINED, EV_RFU1, EV_JOIN_FAILED, EV_REJOIN_FAILED,
142 | EV_TXCOMPLETE, EV_LOST_TSYNC, EV_RESET,
143 | EV_RXCOMPLETE, EV_LINK_DEAD, EV_LINK_ALIVE };
144 | typedef enum _ev_t ev_t;
145 |
146 |
147 | struct lmic_t {
148 | // Radio settings TX/RX (also accessed by HAL)
149 | ostime_t txend;
150 | ostime_t rxtime;
151 | u4_t freq;
152 | s1_t rssi;
153 | s1_t snr;
154 | rps_t rps;
155 | u1_t rxsyms;
156 | u1_t dndr;
157 | s1_t txpow; // dBm
158 |
159 | osjob_t osjob;
160 |
161 | // Channel scheduling
162 | #if defined(CFG_eu868)
163 | band_t bands[MAX_BANDS];
164 | u4_t channelFreq[MAX_CHANNELS];
165 | u2_t channelDrMap[MAX_CHANNELS];
166 | u2_t channelMap;
167 | #elif defined(CFG_us915)
168 | u4_t xchFreq[MAX_XCHANNELS]; // extra channel frequencies (if device is behind a repeater)
169 | u2_t xchDrMap[MAX_XCHANNELS]; // extra channel datarate ranges ---XXX: ditto
170 | u2_t channelMap[(72+MAX_XCHANNELS+15)/16]; // enabled bits
171 | u2_t chRnd; // channel randomizer
172 | #endif
173 | u1_t txChnl; // channel for next TX
174 | u1_t globalDutyRate; // max rate: 1/2^k
175 | ostime_t globalDutyAvail; // time device can send again
176 |
177 | u4_t netid; // current network id (~0 - none)
178 | u2_t opmode;
179 | u1_t upRepeat; // configured up repeat
180 | s1_t adrTxPow; // ADR adjusted TX power
181 | u1_t datarate; // current data rate
182 | u1_t errcr; // error coding rate (used for TX only)
183 | u1_t rejoinCnt; // adjustment for rejoin datarate
184 | s2_t drift; // last measured drift
185 | s2_t lastDriftDiff;
186 | s2_t maxDriftDiff;
187 |
188 | u1_t pendTxPort;
189 | u1_t pendTxConf; // confirmed data
190 | u1_t pendTxLen; // +0x80 = confirmed
191 | u1_t pendTxData[MAX_LEN_PAYLOAD];
192 |
193 | u2_t devNonce; // last generated nonce
194 | u1_t nwkKey[16]; // network session key
195 | u1_t artKey[16]; // application router session key
196 | devaddr_t devaddr;
197 | u4_t seqnoDn; // device level down stream seqno
198 | u4_t seqnoUp;
199 |
200 | u1_t dnConf; // dn frame confirm pending: LORA::FCT_ACK or 0
201 | s1_t adrAckReq; // counter until we reset data rate (0=off)
202 | u1_t adrChanged;
203 |
204 | u1_t margin;
205 | bit_t ladrAns; // link adr adapt answer pending
206 | bit_t devsAns; // device status answer pending
207 | u1_t adrEnabled;
208 | u1_t moreData; // NWK has more data pending
209 | #if !defined(DISABLE_MCMD_DCAP_REQ)
210 | bit_t dutyCapAns; // have to ACK duty cycle settings
211 | #endif
212 | #if !defined(DISABLE_MCMD_SNCH_REQ)
213 | u1_t snchAns; // answer set new channel
214 | #endif
215 | // 2nd RX window (after up stream)
216 | u1_t dn2Dr;
217 | u4_t dn2Freq;
218 | #if !defined(DISABLE_MCMD_DN2P_SET)
219 | u1_t dn2Ans; // 0=no answer pend, 0x80+ACKs
220 | #endif
221 |
222 | // Class B state
223 | #if !defined(DISABLE_BEACONS)
224 | u1_t missedBcns; // unable to track last N beacons
225 | u1_t bcninfoTries; // how often to try (scan mode only)
226 | #endif
227 | #if !defined(DISABLE_MCMD_PING_SET) && !defined(DISABLE_PING)
228 | u1_t pingSetAns; // answer set cmd and ACK bits
229 | #endif
230 | #if !defined(DISABLE_PING)
231 | rxsched_t ping; // pingable setup
232 | #endif
233 |
234 | // Public part of MAC state
235 | u1_t txCnt;
236 | u1_t txrxFlags; // transaction flags (TX-RX combo)
237 | u1_t dataBeg; // 0 or start of data (dataBeg-1 is port)
238 | u1_t dataLen; // 0 no data or zero length data, >0 byte count of data
239 | u1_t frame[MAX_LEN_FRAME];
240 |
241 | #if !defined(DISABLE_BEACONS)
242 | u1_t bcnChnl;
243 | u1_t bcnRxsyms; //
244 | ostime_t bcnRxtime;
245 | bcninfo_t bcninfo; // Last received beacon info
246 | #endif
247 | };
248 | //! \var struct lmic_t LMIC
249 | //! The state of LMIC MAC layer is encapsulated in this variable.
250 | DECLARE_LMIC; //!< \internal
251 |
252 | //! Construct a bit map of allowed datarates from drlo to drhi (both included).
253 | #define DR_RANGE_MAP(drlo,drhi) (((u2_t)0xFFFF<<(drlo)) & ((u2_t)0xFFFF>>(15-(drhi))))
254 | #if defined(CFG_eu868)
255 | enum { BAND_MILLI=0, BAND_CENTI=1, BAND_DECI=2, BAND_AUX=3 };
256 | bit_t LMIC_setupBand (u1_t bandidx, s1_t txpow, u2_t txcap);
257 | #endif
258 | bit_t LMIC_setupChannel (u1_t channel, u4_t freq, u2_t drmap, s1_t band);
259 | void LMIC_disableChannel (u1_t channel);
260 |
261 | void LMIC_enaableChannel (u1_t channel, bit_t fEnableIfTrue);
262 | =======
263 | void LMIC_enableChannel (u1_t channel, bit_t fEnableIfTrue);
264 |
265 | void LMIC_selectSubBand (u1_t uSubBandIndex);
266 | =======
267 | #if defined(CFG_us915)
268 | void LMIC_enableChannel (u1_t channel);
269 | void LMIC_enableSubBand (u1_t band);
270 | void LMIC_disableSubBand (u1_t band);
271 | void LMIC_selectSubBand (u1_t band);
272 | #endif
273 |
274 |
275 | void LMIC_setDrTxpow (dr_t dr, s1_t txpow); // set default/start DR/txpow
276 | void LMIC_setAdrMode (bit_t enabled); // set ADR mode (if mobile turn off)
277 | #if !defined(DISABLE_JOIN)
278 | bit_t LMIC_startJoining (void);
279 | #endif
280 |
281 | void LMIC_shutdown (void);
282 | void LMIC_init (void);
283 | void LMIC_reset (void);
284 | void LMIC_clrTxData (void);
285 | void LMIC_setTxData (void);
286 | int LMIC_setTxData2 (u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed);
287 | void LMIC_sendAlive (void);
288 |
289 | #if !defined(DISABLE_BEACONS)
290 | bit_t LMIC_enableTracking (u1_t tryBcnInfo);
291 | void LMIC_disableTracking (void);
292 | #endif
293 |
294 | #if !defined(DISABLE_PING)
295 | void LMIC_stopPingable (void);
296 | void LMIC_setPingable (u1_t intvExp);
297 | #endif
298 | #if !defined(DISABLE_JOIN)
299 | void LMIC_tryRejoin (void);
300 | #endif
301 |
302 | void LMIC_setSession (u4_t netid, devaddr_t devaddr, xref2u1_t nwkKey, xref2u1_t artKey);
303 | void LMIC_setLinkCheckMode (bit_t enabled);
304 |
305 | // Declare onEvent() function, to make sure any definition will have the
306 | // C conventions, even when in a C++ file.
307 | DECL_ON_LMIC_EVENT;
308 |
309 | // Special APIs - for development or testing
310 | // !!!See implementation for caveats!!!
311 |
312 | #ifdef __cplusplus
313 | } // extern "C"
314 | #endif
315 |
316 | #endif // _lmic_h_
317 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/src/lmic/oslmic.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #include "lmic.h"
13 |
14 | // RUNTIME STATE
15 | static struct {
16 | osjob_t* scheduledjobs;
17 | osjob_t* runnablejobs;
18 | } OS;
19 |
20 | void os_init () {
21 | memset(&OS, 0x00, sizeof(OS));
22 | hal_init();
23 | radio_init();
24 | LMIC_init();
25 | }
26 |
27 | ostime_t os_getTime () {
28 | return hal_ticks();
29 | }
30 |
31 | static u1_t unlinkjob (osjob_t** pnext, osjob_t* job) {
32 | for( ; *pnext; pnext = &((*pnext)->next)) {
33 | if(*pnext == job) { // unlink
34 | *pnext = job->next;
35 | return 1;
36 | }
37 | }
38 | return 0;
39 | }
40 |
41 | // clear scheduled job
42 | void os_clearCallback (osjob_t* job) {
43 | hal_disableIRQs();
44 | unlinkjob(&OS.scheduledjobs, job) || unlinkjob(&OS.runnablejobs, job);
45 | hal_enableIRQs();
46 | }
47 |
48 | // schedule immediately runnable job
49 | void os_setCallback (osjob_t* job, osjobcb_t cb) {
50 | osjob_t** pnext;
51 | hal_disableIRQs();
52 | // remove if job was already queued
53 | os_clearCallback(job);
54 | // fill-in job
55 | job->func = cb;
56 | job->next = NULL;
57 | // add to end of run queue
58 | for(pnext=&OS.runnablejobs; *pnext; pnext=&((*pnext)->next));
59 | *pnext = job;
60 | hal_enableIRQs();
61 | }
62 |
63 | // schedule timed job
64 | void os_setTimedCallback (osjob_t* job, ostime_t time, osjobcb_t cb) {
65 | osjob_t** pnext;
66 | hal_disableIRQs();
67 | // remove if job was already queued
68 | os_clearCallback(job);
69 | // fill-in job
70 | job->deadline = time;
71 | job->func = cb;
72 | job->next = NULL;
73 | // insert into schedule
74 | for(pnext=&OS.scheduledjobs; *pnext; pnext=&((*pnext)->next)) {
75 | if((*pnext)->deadline - time > 0) { // (cmp diff, not abs!)
76 | // enqueue before next element and stop
77 | job->next = *pnext;
78 | break;
79 | }
80 | }
81 | *pnext = job;
82 | hal_enableIRQs();
83 | }
84 |
85 | // execute jobs from timer and from run queue
86 | void os_runloop () {
87 | while(1) {
88 | os_runloop_once();
89 | }
90 | }
91 |
92 | void os_runloop_once() {
93 | osjob_t* j = NULL;
94 | hal_disableIRQs();
95 | // check for runnable jobs
96 | if(OS.runnablejobs) {
97 | j = OS.runnablejobs;
98 | OS.runnablejobs = j->next;
99 | } else if(OS.scheduledjobs && hal_checkTimer(OS.scheduledjobs->deadline)) { // check for expired timed jobs
100 | j = OS.scheduledjobs;
101 | OS.scheduledjobs = j->next;
102 | } else { // nothing pending
103 | hal_sleep(); // wake by irq (timer already restarted)
104 | }
105 | hal_enableIRQs();
106 | if(j) { // run job callback
107 | j->func(j);
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/arduino-lmic-master/src/lmic/oslmic.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | //! \file
13 | #ifndef _oslmic_h_
14 | #define _oslmic_h_
15 |
16 | // Dependencies required for the LoRa MAC in C to run.
17 | // These settings can be adapted to the underlying system.
18 | // You should not, however, change the lmic.[hc]
19 |
20 | #include "config.h"
21 | #include
22 |
23 | #ifdef __cplusplus
24 | extern "C"{
25 | #endif
26 |
27 | //================================================================================
28 | //================================================================================
29 | // Target platform as C library
30 | typedef uint8_t bit_t;
31 | typedef uint8_t u1_t;
32 | typedef int8_t s1_t;
33 | typedef uint16_t u2_t;
34 | typedef int16_t s2_t;
35 | typedef uint32_t u4_t;
36 | typedef int32_t s4_t;
37 | typedef uint64_t u8_t;
38 | typedef int64_t s8_t;
39 | typedef unsigned int uint;
40 | typedef const char* str_t;
41 |
42 | #include
43 | #include "hal.h"
44 | #define EV(a,b,c) /**/
45 | #define DO_DEVDB(field1,field2) /**/
46 | #if !defined(CFG_noassert)
47 | #define ASSERT(cond) if(!(cond)) hal_failed(__FILE__, __LINE__)
48 | #else
49 | #define ASSERT(cond) /**/
50 | #endif
51 |
52 | #define os_clearMem(a,b) memset(a,0,b)
53 | #define os_copyMem(a,b,c) memcpy(a,b,c)
54 |
55 | typedef struct osjob_t osjob_t;
56 | typedef struct band_t band_t;
57 | typedef struct chnldef_t chnldef_t;
58 | typedef struct rxsched_t rxsched_t;
59 | typedef struct bcninfo_t bcninfo_t;
60 | typedef const u1_t* xref2cu1_t;
61 | typedef u1_t* xref2u1_t;
62 | #define TYPEDEF_xref2rps_t typedef rps_t* xref2rps_t
63 | #define TYPEDEF_xref2rxsched_t typedef rxsched_t* xref2rxsched_t
64 | #define TYPEDEF_xref2chnldef_t typedef chnldef_t* xref2chnldef_t
65 | #define TYPEDEF_xref2band_t typedef band_t* xref2band_t
66 | #define TYPEDEF_xref2osjob_t typedef osjob_t* xref2osjob_t
67 |
68 | #define SIZEOFEXPR(x) sizeof(x)
69 |
70 | #define ON_LMIC_EVENT(ev) onEvent(ev)
71 | #define DECL_ON_LMIC_EVENT void onEvent(ev_t e)
72 |
73 | extern u4_t AESAUX[];
74 | extern u4_t AESKEY[];
75 | #define AESkey ((u1_t*)AESKEY)
76 | #define AESaux ((u1_t*)AESAUX)
77 | #define FUNC_ADDR(func) (&(func))
78 |
79 | u1_t radio_rand1 (void);
80 | #define os_getRndU1() radio_rand1()
81 |
82 | #define DEFINE_LMIC struct lmic_t LMIC
83 | #define DECLARE_LMIC extern struct lmic_t LMIC
84 |
85 | void radio_init (void);
86 | void radio_irq_handler (u1_t dio);
87 | void os_init (void);
88 | void os_runloop (void);
89 | void os_runloop_once (void);
90 |
91 | //================================================================================
92 |
93 |
94 | #ifndef RX_RAMPUP
95 | #define RX_RAMPUP (us2osticks(2000))
96 | #endif
97 | #ifndef TX_RAMPUP
98 | #define TX_RAMPUP (us2osticks(2000))
99 | #endif
100 |
101 | #ifndef OSTICKS_PER_SEC
102 | #define OSTICKS_PER_SEC 32768
103 | #elif OSTICKS_PER_SEC < 10000 || OSTICKS_PER_SEC > 64516
104 | #error Illegal OSTICKS_PER_SEC - must be in range [10000:64516]. One tick must be 15.5us .. 100us long.
105 | #endif
106 |
107 | typedef s4_t ostime_t;
108 |
109 | #if !HAS_ostick_conv
110 | #define us2osticks(us) ((ostime_t)( ((s8_t)(us) * OSTICKS_PER_SEC) / 1000000))
111 | #define ms2osticks(ms) ((ostime_t)( ((s8_t)(ms) * OSTICKS_PER_SEC) / 1000))
112 | #define sec2osticks(sec) ((ostime_t)( (s8_t)(sec) * OSTICKS_PER_SEC))
113 | #define osticks2ms(os) ((s4_t)(((os)*(s8_t)1000 ) / OSTICKS_PER_SEC))
114 | #define osticks2us(os) ((s4_t)(((os)*(s8_t)1000000 ) / OSTICKS_PER_SEC))
115 | // Special versions
116 | #define us2osticksCeil(us) ((ostime_t)( ((s8_t)(us) * OSTICKS_PER_SEC + 999999) / 1000000))
117 | #define us2osticksRound(us) ((ostime_t)( ((s8_t)(us) * OSTICKS_PER_SEC + 500000) / 1000000))
118 | #define ms2osticksCeil(ms) ((ostime_t)( ((s8_t)(ms) * OSTICKS_PER_SEC + 999) / 1000))
119 | #define ms2osticksRound(ms) ((ostime_t)( ((s8_t)(ms) * OSTICKS_PER_SEC + 500) / 1000))
120 | #endif
121 |
122 |
123 | struct osjob_t; // fwd decl.
124 | typedef void (*osjobcb_t) (struct osjob_t*);
125 | struct osjob_t {
126 | struct osjob_t* next;
127 | ostime_t deadline;
128 | osjobcb_t func;
129 | };
130 | TYPEDEF_xref2osjob_t;
131 |
132 |
133 | #ifndef HAS_os_calls
134 |
135 | #ifndef os_getDevKey
136 | void os_getDevKey (xref2u1_t buf);
137 | #endif
138 | #ifndef os_getArtEui
139 | void os_getArtEui (xref2u1_t buf);
140 | #endif
141 | #ifndef os_getDevEui
142 | void os_getDevEui (xref2u1_t buf);
143 | #endif
144 | #ifndef os_setCallback
145 | void os_setCallback (xref2osjob_t job, osjobcb_t cb);
146 | #endif
147 | #ifndef os_setTimedCallback
148 | void os_setTimedCallback (xref2osjob_t job, ostime_t time, osjobcb_t cb);
149 | #endif
150 | #ifndef os_clearCallback
151 | void os_clearCallback (xref2osjob_t job);
152 | #endif
153 | #ifndef os_getTime
154 | ostime_t os_getTime (void);
155 | #endif
156 | #ifndef os_getTimeSecs
157 | uint os_getTimeSecs (void);
158 | #endif
159 | #ifndef os_radio
160 | void os_radio (u1_t mode);
161 | #endif
162 | #ifndef os_getBattLevel
163 | u1_t os_getBattLevel (void);
164 | #endif
165 |
166 | #ifndef os_rlsbf4
167 | //! Read 32-bit quantity from given pointer in little endian byte order.
168 | u4_t os_rlsbf4 (xref2cu1_t buf);
169 | #endif
170 | #ifndef os_wlsbf4
171 | //! Write 32-bit quntity into buffer in little endian byte order.
172 | void os_wlsbf4 (xref2u1_t buf, u4_t value);
173 | #endif
174 | #ifndef os_rmsbf4
175 | //! Read 32-bit quantity from given pointer in big endian byte order.
176 | u4_t os_rmsbf4 (xref2cu1_t buf);
177 | #endif
178 | #ifndef os_wmsbf4
179 | //! Write 32-bit quntity into buffer in big endian byte order.
180 | void os_wmsbf4 (xref2u1_t buf, u4_t value);
181 | #endif
182 | #ifndef os_rlsbf2
183 | //! Read 16-bit quantity from given pointer in little endian byte order.
184 | u2_t os_rlsbf2 (xref2cu1_t buf);
185 | #endif
186 | #ifndef os_wlsbf2
187 | //! Write 16-bit quntity into buffer in little endian byte order.
188 | void os_wlsbf2 (xref2u1_t buf, u2_t value);
189 | #endif
190 |
191 | //! Get random number (default impl for u2_t).
192 | #ifndef os_getRndU2
193 | #define os_getRndU2() ((u2_t)((os_getRndU1()<<8)|os_getRndU1()))
194 | #endif
195 | #ifndef os_crc16
196 | u2_t os_crc16 (xref2u1_t d, uint len);
197 | #endif
198 |
199 | #endif // !HAS_os_calls
200 |
201 | // ======================================================================
202 | // Table support
203 | // These macros for defining a table of constants and retrieving values
204 | // from it makes it easier for other platforms (like AVR) to optimize
205 | // table accesses.
206 | // Use CONST_TABLE() whenever declaring or defining a table, and
207 | // TABLE_GET_xx whenever accessing its values. The actual name of the
208 | // declared variable will be modified to prevent accidental direct
209 | // access. The accessor macros forward to an inline function to allow
210 | // proper type checking of the array element type.
211 |
212 | // Helper to add a prefix to the table name
213 | #define RESOLVE_TABLE(table) constant_table_ ## table
214 |
215 | // Accessors for table elements
216 | #define TABLE_GET_U1(table, index) table_get_u1(RESOLVE_TABLE(table), index)
217 | #define TABLE_GET_S1(table, index) table_get_s1(RESOLVE_TABLE(table), index)
218 | #define TABLE_GET_U2(table, index) table_get_u2(RESOLVE_TABLE(table), index)
219 | #define TABLE_GET_S2(table, index) table_get_s2(RESOLVE_TABLE(table), index)
220 | #define TABLE_GET_U4(table, index) table_get_u4(RESOLVE_TABLE(table), index)
221 | #define TABLE_GET_S4(table, index) table_get_s4(RESOLVE_TABLE(table), index)
222 | #define TABLE_GET_OSTIME(table, index) table_get_ostime(RESOLVE_TABLE(table), index)
223 | #define TABLE_GET_U1_TWODIM(table, index1, index2) table_get_u1(RESOLVE_TABLE(table)[index1], index2)
224 |
225 | #if defined(__AVR__)
226 | #include
227 | // Macro to define the getter functions. This loads data from
228 | // progmem using pgm_read_xx, or accesses memory directly when the
229 | // index is a constant so gcc can optimize it away;
230 | #define TABLE_GETTER(postfix, type, pgm_type) \
231 | inline type table_get ## postfix(const type *table, size_t index) { \
232 | if (__builtin_constant_p(table[index])) \
233 | return table[index]; \
234 | return pgm_read_ ## pgm_type(&table[index]); \
235 | }
236 |
237 | TABLE_GETTER(_u1, u1_t, byte);
238 | TABLE_GETTER(_s1, s1_t, byte);
239 | TABLE_GETTER(_u2, u2_t, word);
240 | TABLE_GETTER(_s2, s2_t, word);
241 | TABLE_GETTER(_u4, u4_t, dword);
242 | TABLE_GETTER(_s4, s4_t, dword);
243 |
244 | // This assumes ostime_t is 4 bytes, so error out if it is not
245 | typedef int check_sizeof_ostime_t[(sizeof(ostime_t) == 4) ? 0 : -1];
246 | TABLE_GETTER(_ostime, ostime_t, dword);
247 |
248 | // For AVR, store constants in PROGMEM, saving on RAM usage
249 | #define CONST_TABLE(type, name) const type PROGMEM RESOLVE_TABLE(name)
250 | #else
251 | inline u1_t table_get_u1(const u1_t *table, size_t index) { return table[index]; }
252 | inline s1_t table_get_s1(const s1_t *table, size_t index) { return table[index]; }
253 | inline u2_t table_get_u2(const u2_t *table, size_t index) { return table[index]; }
254 | inline s2_t table_get_s2(const s2_t *table, size_t index) { return table[index]; }
255 | inline u4_t table_get_u4(const u4_t *table, size_t index) { return table[index]; }
256 | inline s4_t table_get_s4(const s4_t *table, size_t index) { return table[index]; }
257 | inline ostime_t table_get_ostime(const ostime_t *table, size_t index) { return table[index]; }
258 |
259 | // Declare a table
260 | #define CONST_TABLE(type, name) const type RESOLVE_TABLE(name)
261 | #endif
262 |
263 | // ======================================================================
264 | // AES support
265 | // !!Keep in sync with lorabase.hpp!!
266 |
267 | #ifndef AES_ENC // if AES_ENC is defined as macro all other values must be too
268 | #define AES_ENC 0x00
269 | #define AES_DEC 0x01
270 | #define AES_MIC 0x02
271 | #define AES_CTR 0x04
272 | #define AES_MICNOAUX 0x08
273 | #endif
274 | #ifndef AESkey // if AESkey is defined as macro all other values must be too
275 | extern xref2u1_t AESkey;
276 | extern xref2u1_t AESaux;
277 | #endif
278 | #ifndef os_aes
279 | u4_t os_aes (u1_t mode, xref2u1_t buf, u2_t len);
280 | #endif
281 |
282 | #ifdef __cplusplus
283 | } // extern "C"
284 | #endif
285 |
286 | #endif // _oslmic_h_
287 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/elapsedMillis/.travis.yml:
--------------------------------------------------------------------------------
1 | language: c
2 | before_install:
3 | - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16"
4 | - sleep 3
5 | - export DISPLAY=:1.0
6 | - wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz
7 | - tar xf arduino-1.6.5-linux64.tar.xz
8 | - sudo mv arduino-1.6.5 /usr/local/share/arduino
9 | - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino
10 |
11 | install:
12 | - ln -s $PWD /usr/local/share/arduino/libraries/elapsedMillis
13 | # - arduino --install-library "elapsedMillis"
14 |
15 | script:
16 | - arduino --verify --board arduino:avr:uno $PWD/examples/GettingStarted/GettingStarted.ino
17 | - arduino --verify --board arduino:avr:uno $PWD/examples/timeouts/timeouts.ino
18 | - arduino --verify --board arduino:avr:uno $PWD/examples/timingComparison/timingComparison.ino
19 |
20 |
21 | notifications:
22 | email:
23 | on_success: change
24 | on_failure: change
25 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/elapsedMillis/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2011 PJRC.COM, LLC
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 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/elapsedMillis/README.md:
--------------------------------------------------------------------------------
1 | elapsedMillis [](https://travis-ci.org/pfeerick/elapsedMillis)
2 | =====================
3 |
4 | These special variable types (*objects*) automatically increase as time elapses. This makes it easy to check if a certain time has elapsed, while allowing your program to perform other work or checks for user input. It is also very to handle multiple tasks requiring different delays.
5 |
6 | Documentation on how to use this library is located in the [wiki](https://github.com/pfeerick/elapsedMillis/wiki) and also on the [Arduino Playground](http://playground.arduino.cc//Code/ElapsedMillis).
7 |
8 | Please report any bugs or issues you find on the [issue tracker](https://github.com/pfeerick/elapsedMillis/issues).
9 |
10 | Initial code derived from Paul Stoffregen's elapsedMillis and elapsedMicros helper code for the Teensy USB developer board. Code contributes and initial examples created by John Plocher.
11 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/elapsedMillis/elapsedMillis.h:
--------------------------------------------------------------------------------
1 | /* Elapsed time types - for easy-to-use measurements of elapsed time
2 | * http://www.pjrc.com/teensy/
3 | * Copyright (c) 2011 PJRC.COM, LLC
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
13 | * all 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
21 | * THE SOFTWARE.
22 | */
23 |
24 | #ifndef elapsedMillis_h
25 | #define elapsedMillis_h
26 | #ifdef __cplusplus
27 |
28 | #if ARDUINO >= 100
29 | #include "Arduino.h"
30 | #else
31 | #include "WProgram.h"
32 | #endif
33 |
34 | class elapsedMillis
35 | {
36 | private:
37 | unsigned long ms;
38 | public:
39 | elapsedMillis(void) { ms = millis(); }
40 | elapsedMillis(unsigned long val) { ms = millis() - val; }
41 | elapsedMillis(const elapsedMillis &orig) { ms = orig.ms; }
42 | operator unsigned long () const { return millis() - ms; }
43 | elapsedMillis & operator = (const elapsedMillis &rhs) { ms = rhs.ms; return *this; }
44 | elapsedMillis & operator = (unsigned long val) { ms = millis() - val; return *this; }
45 | elapsedMillis & operator -= (unsigned long val) { ms += val ; return *this; }
46 | elapsedMillis & operator += (unsigned long val) { ms -= val ; return *this; }
47 | elapsedMillis operator - (int val) const { elapsedMillis r(*this); r.ms += val; return r; }
48 | elapsedMillis operator - (unsigned int val) const { elapsedMillis r(*this); r.ms += val; return r; }
49 | elapsedMillis operator - (long val) const { elapsedMillis r(*this); r.ms += val; return r; }
50 | elapsedMillis operator - (unsigned long val) const { elapsedMillis r(*this); r.ms += val; return r; }
51 | elapsedMillis operator + (int val) const { elapsedMillis r(*this); r.ms -= val; return r; }
52 | elapsedMillis operator + (unsigned int val) const { elapsedMillis r(*this); r.ms -= val; return r; }
53 | elapsedMillis operator + (long val) const { elapsedMillis r(*this); r.ms -= val; return r; }
54 | elapsedMillis operator + (unsigned long val) const { elapsedMillis r(*this); r.ms -= val; return r; }
55 | };
56 |
57 | class elapsedMicros
58 | {
59 | private:
60 | unsigned long us;
61 | public:
62 | elapsedMicros(void) { us = micros(); }
63 | elapsedMicros(unsigned long val) { us = micros() - val; }
64 | elapsedMicros(const elapsedMicros &orig) { us = orig.us; }
65 | operator unsigned long () const { return micros() - us; }
66 | elapsedMicros & operator = (const elapsedMicros &rhs) { us = rhs.us; return *this; }
67 | elapsedMicros & operator = (unsigned long val) { us = micros() - val; return *this; }
68 | elapsedMicros & operator -= (unsigned long val) { us += val ; return *this; }
69 | elapsedMicros & operator += (unsigned long val) { us -= val ; return *this; }
70 | elapsedMicros operator - (int val) const { elapsedMicros r(*this); r.us += val; return r; }
71 | elapsedMicros operator - (unsigned int val) const { elapsedMicros r(*this); r.us += val; return r; }
72 | elapsedMicros operator - (long val) const { elapsedMicros r(*this); r.us += val; return r; }
73 | elapsedMicros operator - (unsigned long val) const { elapsedMicros r(*this); r.us += val; return r; }
74 | elapsedMicros operator + (int val) const { elapsedMicros r(*this); r.us -= val; return r; }
75 | elapsedMicros operator + (unsigned int val) const { elapsedMicros r(*this); r.us -= val; return r; }
76 | elapsedMicros operator + (long val) const { elapsedMicros r(*this); r.us -= val; return r; }
77 | elapsedMicros operator + (unsigned long val) const { elapsedMicros r(*this); r.us -= val; return r; }
78 | };
79 |
80 | #endif // __cplusplus
81 | #endif // elapsedMillis_h
82 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/elapsedMillis/examples/GettingStarted/GettingStarted.ino:
--------------------------------------------------------------------------------
1 | /*
2 | Simple example of using elapsedMillis library
3 |
4 | This example does othing more than blinking a LED... but the difference
5 | here to just using delay(1000) to control the delay between blinks is that
6 | you can do more in the loop - like get user input, check buttons, get sensor
7 | input and other tasks that take time - while you wait for the next time the
8 | LED is to change state. All you need to do is add it before or after the
9 | 'if' statement that controls the check of the time elapsed.
10 |
11 | This example code is in the public domain.
12 | */
13 |
14 | #include
15 |
16 | elapsedMillis timeElapsed; //declare global if you don't want it reset every time loop runs
17 |
18 | // Pin 13 has an LED connected on most Arduino boards.
19 | int led = 13;
20 |
21 | // delay in milliseconds between blinks of the LED
22 | unsigned int interval = 1000;
23 |
24 | // state of the LED = LOW is off, HIGH is on
25 | boolean ledState = LOW;
26 |
27 | void setup()
28 | {
29 | // initialize the digital pin as an output.
30 | pinMode(led, OUTPUT);
31 | }
32 |
33 | void loop()
34 | {
35 | if (timeElapsed > interval)
36 | {
37 | ledState = !ledState; // toggle the state from HIGH to LOW to HIGH to LOW ...
38 | digitalWrite(led, ledState);
39 | timeElapsed = 0; // reset the counter to 0 so the counting starts over...
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/elapsedMillis/examples/timeouts/timeouts.ino:
--------------------------------------------------------------------------------
1 | /*
2 | Using timeouts for user interaction
3 |
4 | A more "real" example than blinking a LED - demonstrate waiting for user input while
5 | flashing a LED in an arbitrary sequence.
6 |
7 | This example code is in the public domain.
8 |
9 | The elapsedMillis() and elapsedMicros() code was originally developed for
10 | the Teensy USB development board (http://www.pjrc.com/teensy/)
11 |
12 | More examples can be found at http://www.pjrc.com/teensy/td_timing.html
13 |
14 | Note that elapsedMillis variables should usually have global scope. If they're
15 | local, they restart from zero every time the function runs, which might be useful
16 | in some cases, but usually you want them to retain their value over longer time.
17 | */
18 |
19 | #include
20 | #include
21 |
22 | #define LEDPIN 13 // The usual Arduino LED port...
23 | #define USERWAITTIME 6000 // milliseconds
24 | #define LEDWAITTIME 35 // milliseconds
25 |
26 | // Many non-trivial Arduino programs benefit from being expressed as a state machine.
27 | // This one encodes the various nuances of accepting user input while still doing
28 | // background work (flashing the LED...)
29 | //
30 | // State machine: a device that can be in one of a set number of stable conditions
31 | // depending on its previous condition and on the present values of
32 | // its inputs.
33 | //
34 | // Alan Skorkin wrote a nice blog about using state machines:
35 | // http://www.skorks.com/2011/09/why-developers-never-use-state-machines/
36 | // in response to this (non-Arduino) post:
37 | // http://www.shopify.com/technology/3383012-why-developers-should-be-force-fed-state-machines#axzz2jvAUuwUj
38 | //
39 | enum State { INIT, NEEDINPUT, WAITING, TIMEOUT, PROCESSING, FINISHED, ERROR } state;
40 |
41 | // The LED would be really boring if it just sat there being either always on or always off
42 | // The array encodes a flash pattern to let you know that nothing is hung...
43 | boolean flashPattern[] = { 1,1,1,1,1,1,1,0,1,1,0 };
44 | unsigned int ledIndex = 0;
45 |
46 | elapsedMillis timeout; // Globally scoped - see comment above
47 | elapsedMillis pulserate;
48 | char userinput;
49 | boolean ledBrightness = HIGH;
50 | String validInput = "YN";
51 |
52 | void setup()
53 | {
54 | //set the LED pin as an output
55 | pinMode(LEDPIN,OUTPUT);
56 |
57 | //Initialize serial and wait for port to open:
58 | Serial.begin(9600);
59 | while (!Serial) {
60 | ; // wait for serial port to connect. Needed for Leonardo only
61 | }
62 | state = INIT;
63 | }
64 |
65 | void loop()
66 | {
67 | // Every time through loop(), the state variable controls what we do.
68 | // As things get done, the state variable is updated to hold the next state.
69 | // The power of a state machine is that it can clearly describe the program
70 | // flow through a complicated decision tree as opposed to a monoithic structure.
71 |
72 | switch (state) {
73 | case INIT: Serial.println("Welcome to the world of elapsed time");
74 | Serial.println("This is a Simple light sequence controller.");
75 | Serial.print("Watch the LED on pin"); Serial.print(LEDPIN, DEC); Serial.println("as you interact with the program.");
76 | state = NEEDINPUT;
77 | break;
78 | case NEEDINPUT: Serial.print("Toggle LED? (Y/n): ");
79 | timeout = 0;
80 | state = WAITING;
81 | break;
82 | case WAITING: if (Serial.available()) {
83 | userinput = toupper(Serial.read());
84 | if (validInput.indexOf(userinput) == -1) {
85 | state = ERROR;
86 | } else {
87 | state = PROCESSING;
88 | }
89 | break;
90 | } else if (timeout > USERWAITTIME) {
91 | state = TIMEOUT;
92 | }
93 | break;
94 | case TIMEOUT: // If you wanted to be obnoxious, you could ring a bell to get the user's attention at this point
95 | Serial.println("");
96 | state = NEEDINPUT;
97 | break;
98 | case PROCESSING: Serial.println(userinput);
99 | // The whole point is to make the flashpattern invert when the user says "Y"
100 | if (userinput == 'Y') ledBrightness = !ledBrightness;
101 | state = NEEDINPUT;
102 | break;
103 | default:
104 | case ERROR: Serial.println(" Braap!");
105 | Serial.print("Expected ["); Serial.print(validInput); Serial.println("], please follow directions!");
106 | state = NEEDINPUT;
107 | break;
108 | }
109 |
110 | if (pulserate > LEDWAITTIME) {
111 | // Demonstrate doing 2 things at once - waiting for input (above) while flashing a LED in a sequence (here)
112 | digitalWrite(LEDPIN, flashPattern[ledIndex++] ? ledBrightness : !ledBrightness);
113 | if (ledIndex > sizeof(flashPattern)) ledIndex = 0;
114 | pulserate = 0;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/elapsedMillis/examples/timingComparison/timingComparison.ino:
--------------------------------------------------------------------------------
1 | /*
2 | Blink with elapsed time
3 | Shows how to use elapsed time to free up your sketch to do interesting work
4 |
5 | This example code is in the public domain.
6 |
7 | The elapsedMillis() and elapsedMicros() code was originally developed for
8 | the Teensy USB development board (http://www.pjrc.com/teensy/)
9 |
10 | Using timers in your code introduces a new concept - variables that
11 | change their value "by themselves"
12 |
13 | The advantage of using timers or elapsed time counters is that you
14 | can use them to free yourself from the busy-wait limitations of
15 | delay(), allowing you to do other work in your sketch.
16 |
17 | Unlike the "int led" variable used below, which is initialized once
18 | and then assumed to always hold the same value, or the ledState
19 | variable that is explicitly set to a new value every time the LED is
20 | turned on or off, the elapsed time datatypes introduced here
21 | automatically update themselves as time passes; their "value" is the
22 | amount of time that has passed since the variable was created or
23 | set. When you set an elapsedMillis variable to 0 (zero), 1
24 | millisecond later it will contain 1, not 0. 1385 milliseconds
25 | later, it will contain 1385.
26 |
27 | You can set/reset these variables to whatever value you want,
28 | whenever you want, and they will be incremented by 1 after each
29 | milli/micro-second of time has passed. You can use them to easily
30 | decide in your program when to do stuff.
31 |
32 | But be careful! Most of the time you will probably want to declare
33 | variables of the elapsedMillis/elpasedMicros data-type globally, at
34 | the top of your sketch. If you define them inside a function() or
35 | in loop(), they will be reset to 0 (zero) each time the function is
36 | called; there they will do a good (but probably unintended) job of
37 | counting the only elapsed time taken since the function was called.
38 |
39 | Both milliseconds and mimicrosecond based interval counters are
40 | supported:
41 | elapsedmillis em1;
42 | elapsedmicros em2;
43 |
44 | All the standard operations are supported on them.
45 |
46 | There are 3 examples below that blink a LED every second.
47 | * The first is the venerable blink sketch that uses delay() to
48 | "do nothing" while waiting for time to pass.
49 | * The second uses calls to millis() to calculate if enough
50 | time has passed, and
51 | * The third is similar, but uses an elapsedmillis variable.
52 |
53 | All three of these are examples of an explicit polling mechanism
54 | - your code continually asks itself "is it time yet", and if so,
55 | does something. The alternative, in situations where much more
56 | exact timing is needed, or if further decoupling is required
57 | between your time-aware code and the rest of your application is
58 | an interrupt handler that takes advantage of the various TIMER
59 | mechanisms that are supported directly by your microcontroller.
60 | For more on using the TIMER hardware directly, see the Arduino
61 | Timer examples on playground:
62 | http://playground.arduino.cc/code/timer1
63 |
64 | More examples can be found at http://www.pjrc.com/teensy/td_timing.html
65 |
66 | */
67 |
68 | #include
69 |
70 | // Pin 13 has an LED connected on most Arduino boards.
71 | int led = 13;
72 |
73 | // the setup routine runs once when you press reset:
74 | void setup() {
75 | // initialize the digital pin as an output.
76 | pinMode(led, OUTPUT);
77 | }
78 |
79 | elapsedMillis elapsedTime; // used by elapsedmilis example
80 | // Globally scoped - see comment above
81 |
82 | unsigned long lasttime = millis(); // used by millis() example...
83 |
84 | unsigned int interval = 1000;
85 | boolean ledState = LOW;
86 |
87 | void loop() {
88 | // delayloop();
89 | // millisloop();
90 | elapsedmillisloop();
91 | }
92 |
93 |
94 | // ########################## delay() based loop ###########################
95 | //
96 | // the loop routine runs over and over again forever,
97 | // but that is all it can do, since the delay() calls preclude
98 | // doing other work...
99 | //
100 | // In this example, the LED blinks on and off once per invocation of loop()
101 |
102 | void delayloop() {
103 | // Note that any "real code" you put here will cause the time between blinks to grow
104 | delay(1000); // wait for a second
105 | // and, finally, blink the lights:
106 |
107 | ledState = !ledState; // toggle the state from HIGH to LOW to HIGH to LOW ...
108 | digitalWrite(led, ledState);
109 | }
110 |
111 |
112 | // ########################## millis() based loop ###########################
113 | //
114 | // the loop routine runs over and over again forever,
115 | // with the blink rate decoupled from however much time the "real code" of the sketch takes
116 | //
117 | // In this example, the blink rate of the LED is independent of the number of times loop()
118 | // is invoked as well as how long it takes to the rest of loop()'s code to run (presuming,
119 | // of course, that the desired blink interval is significantly larger than than that "other"
120 | // time)
121 |
122 | void millisloop() {
123 |
124 | // your "real" code goes here:
125 | // read sensors
126 | // compute new servo positions
127 | // update motor driver output
128 | // and, finally, blink the lights:
129 |
130 | if (millis() - lasttime >= interval) {
131 | ledState = !ledState; // toggle the state from HIGH to LOW to HIGH to LOW ...
132 | digitalWrite(led, ledState);
133 | lasttime = millis();
134 | }
135 | }
136 |
137 | // ########################## elapsedmillis() based loop ###########################
138 | //
139 | // the loop routine runs over and over again forever,
140 | // with the blink rate decoupled from however much time the "real code" of the sketch takes
141 | //
142 | // This example is almost the same as the millis() one, with the various accounting details
143 | // abstracted by the new datatype.
144 |
145 | void elapsedmillisloop() {
146 |
147 | // your "real" code goes here:
148 | // read sensors
149 | // compute new servo positions
150 | // update motor driver output
151 | // and, finally, blink the lights:
152 |
153 | if (elapsedTime > interval) { // Again, note that "elapsedTime" is global scope
154 | ledState = !ledState; // toggle the state from HIGH to LOW to HIGH to LOW ...
155 | digitalWrite(led, ledState);
156 | elapsedTime = 0; // reset the counter to 0 so the counting starts over...
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/elapsedMillis/keywords.txt:
--------------------------------------------------------------------------------
1 | #######################################
2 | # Syntax Coloring Map For elapsedMillis
3 | #######################################
4 |
5 | #######################################
6 | # Datatypes (KEYWORD1)
7 | #######################################
8 |
9 | elapsedMillis KEYWORD1
10 | elapsedMicros KEYWORD1
11 |
12 | #######################################
13 | # Methods and Functions (KEYWORD2)
14 | #######################################
15 |
16 | #######################################
17 | # Constants (LITERAL1)
18 | #######################################
19 |
20 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/elapsedMillis/library.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "elapsedMillis",
3 | "version": "1.0.4",
4 | "keywords": "timing, delay",
5 | "description": "Library for making responsive code easier using elapsed time objects",
6 | "authors":
7 | [
8 | {
9 | "name": "Paul Stoffregen",
10 | "email": "paul@pjrc.com",
11 | "url": "http://pjrc.com/about/contact.html"
12 | },
13 | {
14 | "name": "Peter Feerick",
15 | "email": "peter.feerick@gmail.com",
16 | "url": "https://blog.peterfeerick.com.au/contact/",
17 | "maintainer": true
18 | }
19 | ],
20 | "repository":
21 | {
22 | "type": "git",
23 | "url": "https://github.com/pfeerick/elapsedMillis.git"
24 | },
25 | "frameworks": "arduino"
26 | }
27 |
--------------------------------------------------------------------------------
/ttn-feather-m0/libraries/elapsedMillis/library.properties:
--------------------------------------------------------------------------------
1 | name=elapsedMillis
2 | version=1.0.4
3 | author=Paul Stoffregen
4 | maintainer=Peter Feerick
5 | sentence=Makes coding responsive sketches easier.
6 | paragraph=When using delay(), your code can not (easily) respond to user input while the delay is happening (unless you use interrupts or complex timer code). This library makes this easy by allowing you to create variables (objects) that automatically increase as time elapses. It is easy to check if a certain time has elapsed, while your program performs other work or checks for user input.
7 | category=Timing
8 | url=http://github.com/pfeerick/elapsedMillis/wiki
9 | architectures=*
10 |
--------------------------------------------------------------------------------
/watson-cognitive-servies/twitter-tone-analyzer.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "ea57b254.064e7",
4 | "type": "function",
5 | "z": "4bbf1e34.737f7",
6 | "name": "Add the analyze score to total scores",
7 | "func": "var defaultResult = {\n \"emotion_tone\":{\n \"Anger\":0,\n \"Disgust\":0,\n \"Joy\":0,\n \"Sadness\":0,\n \"Fear\":0\n },\n \"count\":0\n}\n\nif(msg.payload) {\n \n var result = context.get('twitterAnalyze')||defaultResult;\n \n msg.payload.document_tone.tone_categories.forEach(function(toneCategory){\n if(toneCategory.tones){\n toneCategory.tones.forEach(function(tone){\n result[toneCategory.category_id][tone.tone_name] += tone.score;\n })\n }\n })\n result.count += 1;\n\n context.set('twitterAnalyze', result);\n \n return {payload:result};\n}\n",
8 | "outputs": 1,
9 | "noerr": 0,
10 | "x": 394,
11 | "y": 329,
12 | "wires": [
13 | [
14 | "6ebe659e.13311c"
15 | ]
16 | ]
17 | },
18 | {
19 | "id": "6ebe659e.13311c",
20 | "type": "function",
21 | "z": "4bbf1e34.737f7",
22 | "name": "Calculate the average",
23 | "func": "if(msg.payload.count){\n \n msg.type = \"newMsg\";\n\n for (var toneCatogory in msg.payload) {\n // skip loop if the property is from prototype\n if (!msg.payload.hasOwnProperty(toneCatogory)) continue;\n \n var obj = msg.payload[toneCatogory];\n for (var prop in obj) {\n // skip loop if the property is from prototype\n if(!obj.hasOwnProperty(prop)) continue;\n \n obj[prop] = obj[prop]/msg.payload.count;\n }\n } \n}\n\nreturn msg;",
24 | "outputs": 1,
25 | "noerr": 0,
26 | "x": 678,
27 | "y": 330,
28 | "wires": [
29 | [
30 | "c127ce10.5753",
31 | "688d68.2c2ec298",
32 | "d5407ecf.47cfa",
33 | "edc237ef.f4c598",
34 | "adfe5851.814c08"
35 | ]
36 | ]
37 | },
38 | {
39 | "id": "c127ce10.5753",
40 | "type": "change",
41 | "z": "4bbf1e34.737f7",
42 | "name": "Show Anger Score",
43 | "rules": [
44 | {
45 | "t": "set",
46 | "p": "topic",
47 | "pt": "msg",
48 | "to": "Anger",
49 | "tot": "str"
50 | },
51 | {
52 | "t": "set",
53 | "p": "payload",
54 | "pt": "msg",
55 | "to": "payload.emotion_tone.Anger",
56 | "tot": "msg"
57 | }
58 | ],
59 | "action": "",
60 | "property": "",
61 | "from": "",
62 | "to": "",
63 | "reg": false,
64 | "x": 940,
65 | "y": 264,
66 | "wires": [
67 | [
68 | "d48f844e.2ebe38"
69 | ]
70 | ]
71 | },
72 | {
73 | "id": "688d68.2c2ec298",
74 | "type": "change",
75 | "z": "4bbf1e34.737f7",
76 | "name": "Show Disgust Score",
77 | "rules": [
78 | {
79 | "t": "set",
80 | "p": "topic",
81 | "pt": "msg",
82 | "to": "Disgust",
83 | "tot": "str"
84 | },
85 | {
86 | "t": "set",
87 | "p": "payload",
88 | "pt": "msg",
89 | "to": "payload.emotion_tone.Disgust",
90 | "tot": "msg"
91 | }
92 | ],
93 | "action": "",
94 | "property": "",
95 | "from": "",
96 | "to": "",
97 | "reg": false,
98 | "x": 951,
99 | "y": 299,
100 | "wires": [
101 | [
102 | "d48f844e.2ebe38"
103 | ]
104 | ]
105 | },
106 | {
107 | "id": "d5407ecf.47cfa",
108 | "type": "change",
109 | "z": "4bbf1e34.737f7",
110 | "name": "Show Joy Score",
111 | "rules": [
112 | {
113 | "t": "set",
114 | "p": "topic",
115 | "pt": "msg",
116 | "to": "Joy",
117 | "tot": "str"
118 | },
119 | {
120 | "t": "set",
121 | "p": "payload",
122 | "pt": "msg",
123 | "to": "payload.emotion_tone.Joy",
124 | "tot": "msg"
125 | }
126 | ],
127 | "action": "",
128 | "property": "",
129 | "from": "",
130 | "to": "",
131 | "reg": false,
132 | "x": 932,
133 | "y": 333,
134 | "wires": [
135 | [
136 | "d48f844e.2ebe38"
137 | ]
138 | ]
139 | },
140 | {
141 | "id": "edc237ef.f4c598",
142 | "type": "change",
143 | "z": "4bbf1e34.737f7",
144 | "name": "Show Sadness Score",
145 | "rules": [
146 | {
147 | "t": "set",
148 | "p": "topic",
149 | "pt": "msg",
150 | "to": "Sadness",
151 | "tot": "str"
152 | },
153 | {
154 | "t": "set",
155 | "p": "payload",
156 | "pt": "msg",
157 | "to": "payload.emotion_tone.Sadness",
158 | "tot": "msg"
159 | }
160 | ],
161 | "action": "",
162 | "property": "",
163 | "from": "",
164 | "to": "",
165 | "reg": false,
166 | "x": 951,
167 | "y": 367,
168 | "wires": [
169 | [
170 | "d48f844e.2ebe38"
171 | ]
172 | ]
173 | },
174 | {
175 | "id": "adfe5851.814c08",
176 | "type": "change",
177 | "z": "4bbf1e34.737f7",
178 | "name": "Show Fear Score",
179 | "rules": [
180 | {
181 | "t": "set",
182 | "p": "topic",
183 | "pt": "msg",
184 | "to": "Fear",
185 | "tot": "str"
186 | },
187 | {
188 | "t": "set",
189 | "p": "payload",
190 | "pt": "msg",
191 | "to": "payload.emotion_tone.Fear",
192 | "tot": "msg"
193 | }
194 | ],
195 | "action": "",
196 | "property": "",
197 | "from": "",
198 | "to": "",
199 | "reg": false,
200 | "x": 942,
201 | "y": 402,
202 | "wires": [
203 | [
204 | "d48f844e.2ebe38"
205 | ]
206 | ]
207 | },
208 | {
209 | "id": "d48f844e.2ebe38",
210 | "type": "ui_chart",
211 | "z": "4bbf1e34.737f7",
212 | "name": "",
213 | "group": "cd2656a7.d7e078",
214 | "order": 0,
215 | "width": "15",
216 | "height": "10",
217 | "label": "#NationalPetDay Tweets Tone Analyzer",
218 | "chartType": "line",
219 | "legend": "true",
220 | "xformat": "HH:mm:ss",
221 | "interpolate": "linear",
222 | "nodata": "#NationalPetDay Tweets Tone Analyzer",
223 | "ymin": "",
224 | "ymax": "",
225 | "removeOlder": 1,
226 | "removeOlderPoints": "",
227 | "removeOlderUnit": "3600",
228 | "cutout": 0,
229 | "colors": [
230 | "#1f77b4",
231 | "#aec7e8",
232 | "#ff7f0e",
233 | "#2ca02c",
234 | "#98df8a",
235 | "#d62728",
236 | "#ff9896",
237 | "#9467bd",
238 | "#c5b0d5"
239 | ],
240 | "x": 1149,
241 | "y": 324,
242 | "wires": [
243 | [],
244 | []
245 | ]
246 | },
247 | {
248 | "id": "b749b0c0.3652d",
249 | "type": "watson-tone-analyzer-v3",
250 | "z": "4bbf1e34.737f7",
251 | "name": "",
252 | "tones": "emotion",
253 | "sentences": "true",
254 | "contentType": "false",
255 | "x": 474,
256 | "y": 160,
257 | "wires": [
258 | [
259 | "5a731af9.294da4"
260 | ]
261 | ]
262 | },
263 | {
264 | "id": "5a731af9.294da4",
265 | "type": "change",
266 | "z": "4bbf1e34.737f7",
267 | "name": "",
268 | "rules": [
269 | {
270 | "t": "move",
271 | "p": "response",
272 | "pt": "msg",
273 | "to": "payload",
274 | "tot": "msg"
275 | }
276 | ],
277 | "action": "",
278 | "property": "",
279 | "from": "",
280 | "to": "",
281 | "reg": false,
282 | "x": 685,
283 | "y": 159,
284 | "wires": [
285 | [
286 | "ea57b254.064e7"
287 | ]
288 | ]
289 | },
290 | {
291 | "id": "d0857fe9.ef895",
292 | "type": "twitter in",
293 | "z": "4bbf1e34.737f7",
294 | "twitter": "",
295 | "tags": "#NationalPetDay",
296 | "user": "false",
297 | "name": "",
298 | "topic": "tweets",
299 | "inputs": 0,
300 | "x": 100,
301 | "y": 158,
302 | "wires": [
303 | [
304 | "d528ca9c.0fe778"
305 | ]
306 | ]
307 | },
308 | {
309 | "id": "d528ca9c.0fe778",
310 | "type": "delay",
311 | "z": "4bbf1e34.737f7",
312 | "name": "",
313 | "pauseType": "rate",
314 | "timeout": "5",
315 | "timeoutUnits": "seconds",
316 | "rate": "1",
317 | "nbRateUnits": "2",
318 | "rateUnits": "second",
319 | "randomFirst": "1",
320 | "randomLast": "5",
321 | "randomUnits": "seconds",
322 | "drop": false,
323 | "x": 279,
324 | "y": 158,
325 | "wires": [
326 | [
327 | "b749b0c0.3652d"
328 | ]
329 | ]
330 | },
331 | {
332 | "id": "cd2656a7.d7e078",
333 | "type": "ui_group",
334 | "z": "",
335 | "name": "Tone Analyzer",
336 | "tab": "35f07ca9.847544",
337 | "disp": true,
338 | "width": "15"
339 | },
340 | {
341 | "id": "35f07ca9.847544",
342 | "type": "ui_tab",
343 | "z": "",
344 | "name": "Home",
345 | "icon": "dashboard"
346 | }
347 | ]
--------------------------------------------------------------------------------