Il s'agit d'une collection de scripts Python (2 fait, toujours en évolution, plus à venir) et d'autres informations sur la carte de rupture RAK3272S. Pour l'instant, il est livré avec un firmware AT. Étant donné que le STM32WL est une nouvelle puce, il est un peu compliqué de configurer un environnement pour écrire du code C ++ pour cela (j'ai un aperçu de STM32cubeide, et je suis toujours étourdi par la plongée profonde ...), donc pour l'instant, je me concentre sur l'écriture de code qui rend le firmware AT un peu moins douloureux et plus convivial.
Le STM32WL a été ajouté au STM32 Arduino BSP, sans la partie LORA. Une fois que Lora est disponible, je vais porter mon firmware Lora minimal sur cette puce, et nous pourrons utiliser quelque chose d'un peu moins Kludgy. Entre les deux, je vais travailler sur des outils qui imitent le comportement de la Lora minimale.
Il y a 2 scripts qui font une seule chose chacun: recevoir ou envoyer. La façon dont le firmware AT est configuré pour P2P, il est un peu compliqué d'avoir les deux. Fondamentalement, le firmware met la puce en mode TX, et si vous voulez recevoir, vous devez informer le firmware, lui donnant une valeur de délai (idée stupide si vous me demandez). C'est une valeur 16 bits, donc la valeur maximale, 65535, signifie attendre pour toujours. Tout le reste, il attend cette quantité de millisecondes. Pfffrt. Mais ce qui est pire, même si vous êtes en mode "attendre pour toujours", une fois que vous recevez une ligne, vous êtes de retour en mode TX. C'est une cruauté inhabituelle.
J'avais donc deux planches à rupture et chacune était connectée à un ordinateur exécutant un script. Au démarrage, le script met le firmware en mode P2P, configure des paramètres (fréquence, SF, BW, etc.) et définit le mode TX ou RX. Le récepteur se réinitialisera pour recevoir le mode chaque fois qu'un message est reçu.
Étant donné que ces 2 opèrent sur le même réseau d'appareils Bastwan que j'ai, j'ai besoin d'imiter le protocole:
UUID , from et cmd . Après quoi, il peut y avoir ou non d'autres clés. L'expéditeur n'ajoute rien d'autre, mais certains de mes appareils Bastwan le font. Le récepteur sait quoi afficher. Il mène également les paquets afin que vous puissiez conserver un journal de paquets.Dans l'ensemble, ils font déjà un peu. Je cherche à les fusionner et à ajouter plus d'options minimales_lora. Une solution plus robuste pourrait impliquer de créer une application GUI dans Xojo. Nous verrons ...

J'ai ajouté un nouveau script, RAK3272S_Minimal_LoRa.py , qui imite le firmware BastWAN_Minimal_LoRa dans une certaine mesure, et j'ai eu plus de problèmes avec les combinaisons SF / BW liées aux charges utiles. À SF 10, BW 7 (125 kHz), les paquets envoyés à partir des appareils Bastwan sont reçus par l'ensemble du réseau, Bastwan et RAK3272S. D'un autre côté, les paquets envoyés par RAK3272 ne sont pas du tout reçus par des appareils Bastwan et brouillés sur d'autres RAK3272. En vérifiant mon SDR, quelque chose est en effet envoyé, mais les appareils Bastwan ne réagissent même pas. Je pense que le firmware AT, soit le matériel lui-même, est beaucoup plus strict que nécessaire en ce qui concerne les limitations de charge utile: après tout, si les RAK3272 peuvent recevoir des charges utiles longues (~ 180 octets), elle devrait être en mesure de les envoyer également (et elles étaient légèrement plus courtes, environ 160 octets).
Ainsi, même si je m'efforce avec l'équipe de produit, j'ai changé le combo SF / BW en SF 10, BW 9 (500 kHz) et les paquets longs fonctionnent bien maintenant. SF 9, BW 7 semble également fonctionner. J'ajoute divers fichiers JSON PREFS pour les tests. Vous pouvez choisir un fichier PREFS au lancement en faisant:
python3 RAK3272S_Minimal_LoRa.py /dev/tty.usbserial-A901LHDG sf9bw7.json
J'ai ajouté quelques commandes de Minimal_lora:
knownFunctions = [
[ "/p" , sendPing , 0 ], [ "/>" , sendMsg , 1 ], [ "/hm" , setHmac , 1 ],
[ "/cr" , setCr , 1 ], [ "/tx" , setTx , 1 ], [ "/bw" , setBw , 1 ],
[ "/sf" , setSf , 1 ], [ "/r" , setRP , 1 ], [ "/fq" , setFq , 1 ],
[ "/as" , setAs , 1 ], [ "/e" , setEnc , 1 ], [ "/dn" , setDeviceName , 1 ],
[ "/PW" , setPwd , 1 ], [ "/save" , savePrefs , 0 ], [ "/msl" , sendMSL , 1 ],
[ "/gps" , setGPS , 1 ], [ "/help" , showHelp , 0 ]
]C'est encore un peu fragile, mais semble fonctionner assez bien! Amusez-vous!


Ajout d'une fonction calcMaxPayload() qui calcule la charge utile maximale que vous pouvez envoyer en fonction de la configuration SF / BW. Renvoie -1 si (soi-disant de toute façon) invalide. Données provenant de TTN. Ce calcul s'affiche lors de l'appel packOptions() , c'est-à-dire lors de la réinitialisation des options pour la puce.
J'ai refactorisé la partie du code qui analyse l'entrée utilisateur et évalue les commandes. Les commandes, le FN pertinent, et qu'ils aient besoin d'un argument ou non, est stocké dans un tableau, knownFunctions . Une fonction, testFn(line) , analyse le tableau, et s'il trouve une correspondance, appelle la fonction pertinente. Cela rend beaucoup plus facile d'ajouter des commandes.
knownFunctions = [
# Updated list as of 2021/08/05
[ "/p" , sendPing , 0 ], [ "/>" , sendMsg , 1 ], [ "/hm" , setHmac , 1 ],
[ "/cr" , setCr , 1 ], [ "/tx" , setTx , 1 ], [ "/bw" , setBw , 1 ],
[ "/sf" , setSf , 1 ], [ "/r" , setRP , 1 ], [ "/fq" , setFq , 1 ],
[ "/as" , setAs , 1 ], [ "/e" , setEnc , 1 ], [ "/dn" , setDeviceName , 1 ],
[ "/PW" , setPwd , 1 ], [ "/save" , savePrefs , 0 ]
]
def testFn ( line ):
# This function takes one line from user input
# And looks for a know command (see above)
# If the command requires no arguments, 3rd value
# in the array is 0, and the Fn is called as is.
# Or the remainder of the line is passed as argument.
# eg:
# '/p' PING, no argument need. ["/p", sendPing, 0]
# '/fq' Set Frequency, frequency needs to be passed: ["/fq", setFq, 1]
global knownFunctions
for x in knownFunctions :
if line . startswith ( x [ 0 ]):
if x [ 2 ] == 0 :
x [ 1 ]()
else :
param = line [ len ( x [ 0 ]):]
x [ 1 ]( param )
return
print ( "Unknown command!" )J'ai ajouté quelques commandes:
/e0 ~ /e1 éteint les AES ou sur/PWxxxxxx définit le mot de passe sur xxxx/dnxxxxxx définit le nom du périphérique sur xxxx/save enregistre les préfes dans le fichier préfectif actuel 

Intercepté le serial.SerialException soulevé lorsque vous essayez d'ouvrir un port inexistant. Le code existe de manière beaucoup plus propre.

Porté ma fonction C ++ hexDump() sur python pour afficher des paquets sous forme hexagonale à des fins de débogage. Appelé uniquement dans sendPacket() pour l'instant, mais devrait être ajouté plus tard dans quelques autres endroits. Enfin, il sera rendu facultatif avec une définition de #DEBUG .
La fonction a été mise à jour pour permettre des tampons longs que 256 octets.


J'ai ajouté des journaux: les événements principaux (enregistrer les PREFS, les paquets d'envoi / réception) sont enregistrés dans un nouveau fichier de journal, créé à l'heure du démarrage à partir d'un UUID aléatoire: Log_<UUID>.log . Je ferai cette fonctionnalité facultative, mais pour l'instant, pendant que je teste, je vais le laisser allumé.

J'ai ajouté plus de commandes, y compris /help et gps . Cela se reflète également dans les préférences, où la position GPS sera enregistrée, si elle est ajoutée manuellement via la commande /gps . JSON Mot-clé addGPS . Comme indiqué ci-dessous, les commandes /help fournit une explication des commandes (la propriété __doc__ de chaque fonction).
knownFunctions = [
[ "/p" , sendPing , 0 ], [ "/>" , sendMsg , 1 ], [ "/hm" , setHmac , 1 ],
[ "/cr" , setCr , 1 ], [ "/tx" , setTx , 1 ], [ "/bw" , setBw , 1 ],
[ "/sf" , setSf , 1 ], [ "/r" , setRP , 1 ], [ "/fq" , setFq , 1 ],
[ "/as" , setAs , 1 ], [ "/e" , setEnc , 1 ], [ "/dn" , setDeviceName , 1 ],
[ "/PW" , setPwd , 1 ], [ "/save" , savePrefs , 0 ], [ "/msl" , sendMSL , 1 ],
[ "/gps" , setGPS , 1 ], [ "/help" , showHelp , 0 ]
] Voici la sortie de la commande /help :
/help
/p: Sends a ping packet. 0 args
/>: Sends a custom packet (message). 1 args
/hm: Sets HMAC parameter (0/1). 1 args
/cr: Sets C/R parameter (5..8). 1 args
/tx: Sets Tx power (7..22). 1 args
/bw: Sets bandwidth parameter (7..9). 1 args
/sf: Sets spreading factor parameter (6..12). 1 args
/r: Sets pong back parameter (0/1). 1 args
/fq: Sets LoRa frequency. 1 args
/as: Sets autosend parameter (0/XX seconds). 1 args
/e: Sets AES encryption parameter (0/1). 1 args
/dn: Sets device name. 1 args
/PW: Sets AES encryption key. 1 args
/save: Saves preferences to disk. 0 args
/msl: Sets Mean Sea Level air pressure (dor altitude calculation). 1 args
/gps: Sets GPS coords (or turns off GPS location). 1 args
/help: Shows this help. 0 args
