My thought is to take the thethingsnetwork-send-v1 example program from Dragino’s Raspberry Pi port at https://github.com/dragino/lmic_pi/tree/master/examples and adapt it to take in command line arguments that specify the various keys needed and allow arbitrary hex data to be specified. example:
Unfortunately I have found the Dragino hat to be rather unstable with lmic (the same problems with radio.c and lmic.c ASSERTS discussed elsewhere) so it is making it difficult to test.
In general you’ll want OTAA, not ABP, so you need to store the result of the OTAA Join Accept.
For Class A devices (the only thing supported by TTN’s community network right now), LMIC needs to await possible downlinks. For an OTAA Join Accept, that is sent after either 5 or 6 seconds; for a regular uplink after 1 or 2 seconds.
So, a command line ttn-send will always run for at least 1 second, and most often 2 seconds as in general no downlink will be sent at all for which LMIC needs to check both RX1 and RX2. Things will be worse when an OTAA join fails, or when using a confirmed uplink and no ACK is received, and LMIC needs to repeat the uplink.
Hence, if you want any sensors to be read in the meantime, you’ll need to run multiple processes simultaneously, and take care that at most one instance of ttn-send will run at any time. When adding one’s own code to LMIC instead, then LMIC can do its housekeeping whenever running os_runloop_once, and sensors can be processed even while awaiting a possible downlink; see also https://www.thethingsnetwork.org/forum/t/how-do-i-run-non-lorawan-code-in-lmic/22575/8.
LMIC keeps track of many more things: most importantly the duty cycle and frame counters, but also things like ADR for which it needs to keep specific counters, and then in some uplinks might need to set a specific bit to trigger ADR or include a MAC command to confirm the settings that the server gave it earlier. So, you’ll need to store the full LMIC state between invocations of the command line version, and make sure it uses the correct time to do its duty cycle calculations. See What LMIC state must be preserved during sleep mode?
Thanks for the information…it might make more sense then to have the command line program send the data to a queue/other input to the running lmic program which can read from the queue every cycle. That way lmic can preserve the state.
I took a few hours and implemented the ttn-send utility I described above. What I did was to clone the standard lmic base and created YAGP (yet another git project) and did some modifications to the thethingsnetwork-send-v1 example. The executable now runs a socket server and receives strings from the ttn-send client program and sends them out during the upload cycle.
An example run is this:
Start the lmic core and a socket server listening on port 8877:
./thethingsnetwork-send-v1 -p 8877 &
p - port of server
h - host of server
a - appeui
d - deveui
n - network key
s - session key
e - devaddr of node
x - arbitrary string of hex bytes to send
Given the above input it should send the bytes 010203040506 to TTN:
The repo is here:
I also messed with the frequencies in lorabase.h because the Dragino hat doesn’t seem to be frequency hopping correctly (or lmic isn’t doing it right). I also have it configured for US915.
I tested it with the Dragino Hat 1.4 and RPI3 and a Laird RG1xx gateway.
It probably makes more sense to use MQTT for this instead of custom socket code.
I’d be a little worried about doing this under a multi-tasking OS. If you expect to catch downlink windows you probably want to modify the timing to spin up the radio a bit early for receive, and to search for a longer than usual interval of symbols, as scheduler latency under system load could otherwise cause you to miss downlink windows when timed as tight as it would typically be in on an MCU platform with goals of saving battery power.
In contrast, when a gateway runs on a multi-tasking OS the precise timing is done in hardware with the 1301’s rolling microsecond counter.
That might be the case. The “thethingsnetwork-sendv1” example only sends through, it doesn’t receive. However I have tested the receive and it does seem to work. lmic in general seems like more of a proof of concept stack to me, rather than a production solution.