Comments (14)
As it stands no but the changes to make it work are relatively simple. I have this working for a project I worked on last year.
Firstly you need to add a new function to register the callback function.
Secondly, you need to make changes to the on_rx_done() function in dragino.py.
step 1 - add a variable to hold the callback function address in class Dragino __init__()
self.msgCallback=None
step 2 - add a new method to class Dragino
def setMsgCallback(self,callback):
self.msgCallback=callback
step 3 modify class Dragino on_rx_done() - this is my changed on_rx_done(). Note this change only looks for unconfirmed downlink messages i.e. TTN isn't expecting a reply.
def on_rx_done(self):
"""
Callback on RX complete, signalled by I/O
"""
self.clear_irq_flags(RxDone=1)
self.logger.debug("on_rx_done() Received downlink message")
payload = self.read_payload(nocheck=True)
if payload is None:
self.logger("on_rx_done() Received message but payload is None")
return
self.logger.debug("on_rx_done() payload="+"".join(format(x, '02x') for x in bytes(payload)))
try:
if self.network_key is None: # not joined yet
self.logger.debug("on_rx_done() processing JOIN_ACCEPT payload")
lorawan = lorawan_msg([], self.appkey)
lorawan.read(payload)
lorawan.get_payload()
else:
self.logger.info("on_rx_done() processing payload after joined")
lorawan = lorawan_msg(self.network_key, self.apps_key)
lorawan.read(payload)
decodedPayload=lorawan.get_payload()
self.logger.debug("on_rx_done() decodedPayload=%s", decodedPayload)
except Exception as e:
self.logger.exception("on_rx_done() exception %s",e)
return None
self.logger.debug("on_rx_done() mversion=%s", lorawan.get_mhdr().get_mversion())
mtype=lorawan.get_mhdr().get_mtype()
if mtype == MHDR.JOIN_ACCEPT:
self.logger.info("on_rx_done() Processing JOIN_ACCEPT")
#It's a response to a join request
lorawan.valid_mic()
self.device_addr = lorawan.get_devaddr()
self.logger.debug("on_rx_done() Device: %s", self.device_addr)
self.network_key = lorawan.derive_nwskey(self.devnonce)
self.logger.debug("on_rx_done() Network key: %s", self.network_key)
self.apps_key = lorawan.derive_appskey(self.devnonce)
self.logger.debug("on_rx_done() APPS key: %s", self.apps_key)
return
elif mtype == MHDR.UNCONF_DATA_DOWN:
self.logger.info("on_rx_done() processing UNCONF_DATA_DOWN")
try:
# keys obtained at OTAA join?
lorawan = lorawan_msg(self.network_key, self.apps_key)
lorawan.read(payload)
decodedPayload = lorawan.get_payload()
# note downlink messages are hex bytes in the TTN console
self.logger.debug("on_rx_done() UNCONF_DATA_DOWN decodedPayload %s",decodedPayload)
if self.msgCallback is not None:
self.logger.info("on_rx_done() starting callback to downlink manager")
self.msgCallback(decodedPayload)
else:
self.logger.error("on_rx_done() no callback configured")
return
except Exception as e:
self.logger.exception("on_rx_done() UNCONF_DATA_DOWN %s",e)
return
elif mtype == MHDR.CONF_DATA_DOWN :
self.logger.warning("on_rx_done() CONF_DATA_DOWN - not supported")
#if self.msgCallback is not None:
# self.logger.info("on_rx_done() starting callback to downlink manager")
# self.msgCallback(payload)
else:
self.logger.info("on_rx_done() callback ignored mtype=%s",mtype)
This works for me on an older version (last year) of this code. I haven't, but need to, modified the latest version
Be aware that queued downlink messages might only sent be after TTN sees an uplink message - depends which LoraWAN class you use. In my use case the uplink message interval was about 6 minutes so that would be the rate that downlinks could be sent.
Note, also, that the get_gps() method is not blocking (albeit for a configurable wait period). But that's another story.
from dragino.
I'm afraid I don't have time to add that into the main code, but if either of you would like to do so and issue a pull request I'll happily review.
from dragino.
I'll be updating my modified copy of your code in the near future, with your latest version. I've never done a pull request before so not sure how to go about that other than to attach the changed file (dragino.py) for you to look at.
from dragino.
Thank you. There's plenty of documentation about how to do a pull request. The short version is you create your own fork of the code make the changes to it, and then use the pull request tab on this project to create a request to merge the changes from your version into this version.
from dragino.
Ok, I'll try doing it that way.
from dragino.
Just looking at adding something to readme.md - the todo list includes adding GPS support but that is already included. Does readme.md need to be updated?
from dragino.
Almost certainly!
from dragino.
I have made the required changes but have yet to test on my Dragino - busy busy , like you, with more critical stuff. But I'll get there.
from dragino.
Thanks for working on this :)
from dragino.
Having some problems with receiving downlinks (Other than JOIN_ACCEPT).
Each time an uplink is sent the dragino.py code chooses a different frequency (it stayed with one frequency before IIRC). If TTN does not send the downlink on the current frequency then the downlink message is lost. The question is "How long to wait for a possible downlink message before we can transmit again, on a randomly selected frequency". When I get my test code sorted out I'll try to put a number on that but I suspect there will be a lot of lost downlink messages and they are thwarting my testing.
One other issue I had was shutting down my dragino overnight - It would not talk to TTN the next day. This, I think, has something to do with credential caching and (maybe) aging thereof (but not sure). I removed the appskey/devaddr and nwkskey which had been appended to the dragino.ini file and finally got the dragino and TTN talking to each other again. Personally I would prefer the caching to go in a seperate file and maybe add a timestamp to check it's staleness. If stale then issue a rejoin before a send. Possibly that could be controlled by the code using dragino.py but would need a good explanation/example for people to follow.
Back to the grindstone...
from dragino.
The LoRaWAN specs include the details of how long a device should wait for messages after transmit (class A), and to listen all the time (class C), I've not looked into the channel assignment for downlink - I think it works differently to uplink.
I believe that once cached OTAA credentials ahould not expire and so can be re-used for as long as needed, although I don't have time to find the reference for that now. In my testing with v3 the OTAA has seemed more solid than ABP which would often just get dropped.
from dragino.
Yes of course. I forgot about rx1 and rx2 though rx2 is a different frequency to rx1 iirc.
from dragino.
It's working now. A bit of tidying up and I'll be ready to push/pull.
from dragino.
The original request for downlink support is has been implemented by #11 and is now in release v0.0.06 (https://github.com/computenodes/dragino/releases/tag/v0.0.6)
I've found blog posts from TTN from a few years ago saying that OTAA sessions will don't expire https://www.thethingsnetwork.org/forum/t/lorawan-session-termination-expiration/3556 The most recent documentation I've found https://www.thethingsindustries.com/docs/devices/abp-vs-otaa/ says that the OTAA credentials can be cached and then used at a later date.
The best practice would be to occasionally send uplinks with Acks and after X messages where you don't get an Ack back perform a rejoin, but that's a subject for another issue/discussion.
As the requested down link functionality is now in the code I'll close this one.
from dragino.
Related Issues (19)
- Support SF12 & RX2 HOT 4
- Dragino LoRa/GPS HAT on RPi 4 HOT 1
- Change the DevNonce when retrying a join. HOT 2
- Unable to join to TTN V3 HOT 5
- dio_mapping needs to be reset in join() HOT 1
- Add tx_done flag HOT 1
- Confirmed downlink messages? HOT 1
- Seeing more downlink messages than expected in TTS HOT 7
- Routing downlink messages HOT 2
- Possible race condition waiting for 'transmitting' flag to become False
- DevNonce changes in 1.0.4 HOT 2
- Downlink Messages HOT 2
- OTTA implementation HOT 11
- Can't get test.py to work HOT 6
- OTAA - waiting repeats.... v2 ttn and v3 both see the activation. HOT 6
- TTN V3 Compatability HOT 2
- Compatibility with Adafruit RFM95W? HOT 2
- test.py has problem reading dragino.ini file HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dragino.