├── 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 \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 \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 \n \n \n \n \n \n \n \n \n \n \n
IndexTimestampValueBool
{{$index}}{{msg.payload[$index].TIMESTAMP}}{{msg.payload[$index].VALUE}}{{msg.payload[$index].BOOL}}
", 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 [![Build Status](https://travis-ci.org/pfeerick/elapsedMillis.svg?branch=master)](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 | ] --------------------------------------------------------------------------------