Un ttnpb.ApplicationUp
devrait pouvoir générer plusieurs messages frontaux, au lieu d'un seul.
Actuellement, un ttnpb.ApplicationUp
est rassemblé en une seule tranche d'octets qui se traduit par un message frontal (un appel HTTP, un message MQTT, etc.). Cependant, si la charge utile de la liaison montante contient plusieurs mesures (pensez à plusieurs capteurs connectés à un seul appareil), il serait utile de permettre à certains formats de créer plusieurs messages pour chaque mesure.
https://github.com/TheThingsNetwork/lorawan-stack/blob/9112dd7bcd3f1f03190055542908b427b27acd1c/pkg/applicationserver/io/formatters/formatter.go#L23
Le format ne renvoie actuellement qu'un seul message à envoyer aux frontaux.
Le résultat doit être modifié de []byte
à [][]byte
.
93ea01b4b5af2672da5883b570be825a54b8afc1
Modifiez l'interface Format
. Après cela, chaque frontal doit être modifié pour envoyer tous les messages au lieu d'un seul :
[]http.Request
au lieu de http.Request
), et le résultat de format.FromUp
doit être utilisé pour créer ces requêtes.topic.Send
pour chaque résultat de i.format.FromUp
.[][]byte
, car le format JSON par défaut ne renvoie qu'un seul message.Oui, mais je laisse cela à la communauté.
@adriansmares Je travaille actuellement sur ce problème. Après être passé de []byte à [][]byte pour la fonction *ttnpb.ApplicationUp dans le fichier formatter.go, je l'ai également modifié dans les fichiers json.go et protobuf.go. Mais maintenant, cela donne l'erreur suivante:
Veuillez fournir une suggestion. Merci.
@mihirr93 Puisque vous modifiez maintenant les sites d'appel pour renvoyer une tranche de résultats (chaque résultat étant une tranche d'octets), vous devez envelopper les endroits où un seul résultat est renvoyé avec [][]byte{ slice-containing-result }
.
Bonjour M. @adriansmares . Je suis un peu confus quant à notre approche. Nous essayons de découper le message frontal (charge utile brute) en plusieurs messages. Mais dans ce cas, le point auquel le message sera découpé dépend de son encodage (Cayenne ou tout encodage personnalisé) qui nous est inconnu. Donc, pour ce faire, nous devons utiliser la charge utile décodée. Une fois que l'utilisateur a entré le décodeur dans l'onglet format de charge utile du TTN, l'application affiche en fait les valeurs décodées en JSON (comme on le voit sur l'image). Ne devrions-nous pas directement diviser cette charge utile décodée et la pousser plus loin en utilisant http ?
Pourriez-vous s'il vous plaît éclairer cette confusion?
Et, modifions-nous simplement les fichiers pkg et les fichiers .proto seront-ils automatiquement mis à jour ?
Merci beaucoup pour votre soutien et votre temps.
_Keep à l' esprit que ce référentiel contient la version V3 de notre pile lorawan, et l'image fournie est de TTN, qui dirige la V2 version._
Veuillez garder à l'esprit que ce problème ne traite que de la prise en charge de la production de plusieurs charges utiles à partir d'un seul message, et le nouveau problème de format qui vous intéresse probablement est https://github.com/TheThingsNetwork/lorawan-stack/issues/1158. Veuillez vérifier si ce problème est bien celui que vous recherchez.
Néanmoins, je suggérerais dans ce cas que vous introduisiez un nouveau format, basé sur celui de JSON , qui produit plusieurs charges utiles basées sur les informations décodées trouvées dans la liaison montante.
Vous voudrez probablement gérer spécifiquement le message de liaison montante ApplicationUp_UplinkMessage
, car il contient les champs qui vous intéressent dans le cadre du champ DecodedPayload
.
Vous ne devriez pas avoir à modifier les fichiers proto pour ce cas d'utilisation.
J'essaie toujours de comprendre le fonctionnement interne et le code de la pile. Actuellement, je me concentre uniquement sur ce problème, et non sur le #1158. Comme vous avez suggéré de modifier le ApplicationUp_Uplinkmessage
, j'essaie de comprendre cela. J'ai les requêtes suivantes en ce moment :
1) La struct ApplicationUplink
et la fonction ApplicationUp_UplinkMessage
sont définies dans le fichier messages.pb.go du répertoire ttnpb. Cependant l'en-tête du fichier mentionne "NE PAS EDITER". Dois-je l'ignorer ? ou existe-t-il une autre approche pour le modifier?
2) Pouvez-vous s'il vous plaît décrire cela plus en détail " introduce a new format, based on the JSON one
" ? J'ai pensé qu'il suffisait de modifier le format existant au lieu d'en créer un nouveau.
3) Vous avez également mentionné l'emballage des résultats où un seul résultat est renvoyé. Qu'est-ce que ça va faire exactement ? Re-combinera-t-il le message multiple en un seul et renverra-t-il un seul résultat ? Et devons-nous le faire uniquement pour le message Uplink ?
[Merci @adriansmares pour vos conseils continus. Bien que j'ai suivi le didacticiel sur le golang, c'est ma première interaction avec le langage GO, excusez-moi de vous déranger avec tant de doutes]
*.pb.*
. Ceux-ci sont générés automatiquement à partir des fichiers *.proto
lorsque vous exécutez mage proto:all
. Néanmoins, pour les besoins de ce numéro, aucune modification de ce type n'est nécessaire.Laissez-moi essayer de mieux expliquer l'ensemble du pipeline, peut-être que cela nous éclairera sur la façon dont cela fonctionne
*ttnpb.ApplicationUplink
.FRMPayload
dans la structure décodée de DecodedPayload
) à l'aide du formateur de charge utile de l'appareil.*ttnpb.ApplicationUp
et l'envoie aux frontends (MQTT, webhooks, PubSub, packages d'application).*ttnpb.ApplicationUp
et en fonction de leurs paramètres (le format) choisissent le formateur à utiliser (l'interface du formateur est définie dans pkg/applicationserver/io/formatters
).formatter.FromUp
avec le 1 *ttnph.ApplicationUp
et reçoit une tranche d'octet ( []byte
), représentant le corps de 1 message.Maintenant, concernant ce problème, j'espère qu'il est visible que seule l'étape 6 a besoin de modifications :
FromUp
puisse renvoyer plusieurs charges utiles (une tranche de tranches d'octet).Protobuf
et JSON
existants ne devraient pas changer leur comportement et, en tant que tels, devraient continuer à ne renvoyer qu'une seule charge utile (c'est pourquoi le wrapping est requis).[][]byte
vous commencerez à voir des erreurs (puisque la plupart des endroits qui appellent FromUp
s'attendent Ce n'est qu'après la résolution de ce problème, qui ne modifie en rien le comportement, que vous pouvez implémenter votre propre formateur, qui renverrait une tranche de plusieurs charges utiles, une pour chaque mesure (mais gardez à l'esprit que ce nouveau format est hors de portée pour ce problème !).
Merci beaucoup @adriansmares pour une explication et un guide si détaillés. Je pense avoir réussi à résoudre ce problème maintenant. Je l'ai également testé avec ./mage go:test js:test jsSDK:test
et il ne donne aucune erreur. Les principales modifications apportées au code sont mises en évidence ci-dessous :
formateur.aller
type Formatter interface {
FromUp(*ttnpb.ApplicationUp) ([][]byte, error)
ToDownlinks([]byte) (*ttnpb.ApplicationDownlinks, error)
ToDownlinkQueueRequest([]byte) (*ttnpb.DownlinkQueueRequest, error)
}
json.go
func (json) FromUp(msg *ttnpb.ApplicationUp) ([][]byte, error) {
m, e := jsonpb.TTN().Marshal(msg)
return [][]byte{m}, e
}
protobuf.go
Comme ci-dessus
mqtt.go
buf, err := c.format.FromUp(up.ApplicationUp)
if err != nil {
logger.WithError(err).Warn("Failed to marshal upstream message")
continue
}
logger.Debug("Publish upstream message")
for _, v := range buf {
c.session.Publish(&packet.PublishPacket{
TopicName: topic.Join(topicParts),
TopicParts: topicParts,
QoS: qosUpstream,
Message: v,
})
}
pubsub.go
Comme ci-dessus
webhooks.go
unc (w *webhooks) newRequest(ctx context.Context, msg *ttnpb.ApplicationUp, hook *ttnpb.ApplicationWebhook) ([]*http.Request, error) {
var cfg *ttnpb.ApplicationWebhook_Message
switch msg.Up.(type) {
case *ttnpb.ApplicationUp_UplinkMessage:
cfg = hook.UplinkMessage
case *ttnpb.ApplicationUp_JoinAccept:
cfg = hook.JoinAccept
case *ttnpb.ApplicationUp_DownlinkAck:
cfg = hook.DownlinkAck
case *ttnpb.ApplicationUp_DownlinkNack:
cfg = hook.DownlinkNack
case *ttnpb.ApplicationUp_DownlinkSent:
cfg = hook.DownlinkSent
case *ttnpb.ApplicationUp_DownlinkFailed:
cfg = hook.DownlinkFailed
case *ttnpb.ApplicationUp_DownlinkQueued:
cfg = hook.DownlinkQueued
case *ttnpb.ApplicationUp_LocationSolved:
cfg = hook.LocationSolved
}
if cfg == nil {
return nil, nil
}
url, err := url.Parse(hook.BaseURL)
if err != nil {
return nil, err
}
url.Path = path.Join(url.Path, cfg.Path)
expandVariables(url, msg)
if err != nil {
return nil, err
}
format, ok := formats[hook.Format]
if !ok {
return nil, errFormatNotFound.WithAttributes("format", hook.Format)
}
buf, err := format.FromUp(msg)
if err != nil {
return nil, err
}
var requests []*http.Request
for i, v := range buf {
req, err := http.NewRequest(http.MethodPost, url.String(), bytes.NewReader(v))
requests[i] = req
if err != nil {
return nil, err
}
for key, value := range hook.Headers {
req.Header.Set(key, value)
}
if hook.DownlinkAPIKey != "" {
req.Header.Set(downlinkKeyHeader, hook.DownlinkAPIKey)
req.Header.Set(downlinkPushHeader, w.createDownlinkURL(ctx, hook.ApplicationWebhookIdentifiers, msg.EndDeviceIdentifiers, "push"))
req.Header.Set(downlinkReplaceHeader, w.createDownlinkURL(ctx, hook.ApplicationWebhookIdentifiers, msg.EndDeviceIdentifiers, "replace"))
}
req.Header.Set("Content-Type", format.ContentType)
req.Header.Set("User-Agent", userAgent)
}
return requests, nil
}
Veuillez fournir vos commentaires et commentaires. Je ferai les corrections (nommage Var, indentation, etc.) selon les directives de style de code une fois la tâche complètement terminée. Et si cela semble correct, pourriez-vous s'il vous plaît me guider davantage pour le problème #1158 . Merci une fois de plus.
@mihirr93 a l' air bien ! Veuillez valider vos modifications et soumettre une demande d'extraction pour ce problème. Après l'avoir fusionné, nous pouvons passer au nouveau formateur mentionné dans #1158.
@adriansmares Bien sûr, je vais le faire. Cette demande d'extraction doit-elle être basée sur l'environnement mentionné ou sur la dernière version de la pile ?
Je vous recommande de rebaser vos modifications sur les derniers master
afin d'éviter les conflits plus tard.
Ce problème est inactif depuis un certain temps, alors ramenons-le au triage pour voir s'il y a toujours une demande pour cela, ou si nous devrions simplement le laisser tomber.
Ce n'est plus nécessaire, car il évolue mal.