Ein ttnpb.ApplicationUp
sollte zu mehreren Front-End-Nachrichten führen können, anstatt nur einer.
Derzeit wird ein ttnpb.ApplicationUp
in nur einen Byte-Slice gemarshallt, der zu einer Front-End-Nachricht führt (ein HTTP-Aufruf, eine MQTT-Nachricht usw.). Wenn die Nutzlast des Uplinks jedoch mehrere Messungen enthält (denken Sie an mehrere Sensoren, die an ein Gerät angeschlossen sind), wäre es hilfreich, bestimmte Formate zuzulassen, um mehrere Nachrichten für jede Messung zu erstellen.
https://github.com/TheThingsNetwork/lorawan-stack/blob/9112dd7bcd3f1f0319005542908b427b27acd1c/pkg/applicationserver/io/formatters/formatter.go#L23
Das Format gibt derzeit nur eine Nachricht zurück, die an die Front-Ends gesendet werden soll.
Das Ergebnis sollte von []byte
in [][]byte
geändert werden.
93ea01b4b5af2672da5883b570be825a54b8afc1
Ändern Sie die Format
Schnittstelle. Danach sollte jedes Frontend so geändert werden, dass alle Nachrichten statt nur einer gesendet werden:
[]http.Request
statt http.Request
), und das Ergebnis von format.FromUp
sollte verwendet werden, um diese Anfragen zu erstellen.topic.Send
für jedes Ergebnis von i.format.FromUp
.[][]byte
, da das Standard-JSON-Format nur eine Nachricht zurückgibt.Ja, aber das überlasse ich der Community.
@adriansmares Ich arbeite gerade an diesem Thema. Nachdem ich für die Funktion *ttnpb.ApplicationUp in der Datei formatter.go von []byte zu [][]byte gewechselt habe, habe ich sie auch in den Dateien json.go und protobuf.go geändert. Aber jetzt gibt es folgenden Fehler:
Bitte geben Sie einen Vorschlag. Dankeschön.
@mihirr93 Da Sie jetzt die [][]byte{ slice-containing-result }
.
Hallo Herr @adriansmares . Ich bin etwas verwirrt über unseren Ansatz. Wir versuchen, die Front-End-Nachricht (rohe Nutzlast) in mehrere Nachrichten aufzuteilen. Aber in diesem Fall hängt der Punkt, an dem die Nachricht geschnitten wird, von ihrer Codierung (Cayenne oder eine andere benutzerdefinierte Codierung) ab, die uns unbekannt ist. Dazu müssen wir also die decodierte Nutzlast verwenden. Sobald der Benutzer den Decoder im Payload-Format-Tab des TTN eingibt, zeigt die Anwendung die decodierten Werte tatsächlich in JSON an (wie im Bild zu sehen). Sollten wir diese dekodierte Nutzlast nicht direkt aufteilen und mit http weiter pushen?
Könnten Sie bitte etwas Licht in diese Verwirrung bringen?
Und ändern wir nur die pkg-Dateien und die .proto-Dateien werden automatisch aktualisiert?
Vielen Dank für Ihre freundliche Unterstützung und Zeit.
_Denken Sie daran, dass dieses Repository die V3-Version unseres LoRaWAN-Stacks enthält und das bereitgestellte Bild von TTN stammt, auf dem die V2- Version ausgeführt wird._
Bitte beachten Sie, dass dieses Problem nur die Unterstützung für die Erstellung mehrerer Nutzlasten aus einer Nachricht betrifft, und das neue Formatproblem, an dem Sie wahrscheinlich interessiert sind, ist https://github.com/TheThingsNetwork/lorawan-stack/issues/1158. Bitte überprüfen Sie, ob dieses Problem tatsächlich das ist, nach dem Sie suchen.
Trotzdem würde ich in diesem Fall vorschlagen, ein neues Format einzuführen, das auf JSON basiert, das basierend auf den decodierten Informationen im Uplink mehrere Nutzlasten erzeugt.
Sie werden wahrscheinlich die Uplink-Nachricht ApplicationUp_UplinkMessage
speziell behandeln wollen, da sie die Felder enthält, die Sie als Teil des Feldes DecodedPayload
interessieren.
Sie sollten die Proto-Dateien für diesen Anwendungsfall nicht ändern müssen.
Ich versuche immer noch, die interne Arbeitsweise und den Code des Stapels zu verstehen. Derzeit konzentriere ich mich nur auf dieses Thema und nicht auf #1158. Da Sie vorgeschlagen haben, ApplicationUp_Uplinkmessage
zu ändern, versuche ich, das herauszufinden. Ich habe im Moment folgende Fragen:
1) Die Struktur ApplicationUplink
und die Funktion ApplicationUp_UplinkMessage
sind in der Datei messages.pb.go im Verzeichnis ttnpb definiert. Im Header der Datei steht jedoch "DO NOT EDIT". Soll ich es ignorieren? oder gibt es einen alternativen Ansatz, um es zu ändern?
2) Können Sie dies bitte genauer beschreiben " introduce a new format, based on the JSON one
"? Ich dachte, wir müssen nur das bestehende Format ändern, anstatt ein neues zu erstellen.
3) Sie haben auch das Umschließen von Ergebnissen erwähnt, bei dem nur ein Ergebnis zurückgegeben wird. Was genau wird das bewirken? Wird es die Mehrfachnachricht wieder zu einer kombinieren und nur ein Ergebnis zurückgeben? Und müssen wir das nur für Uplink-Nachrichten tun?
[Danke @adriansmares für deine kontinuierliche Anleitung. Obwohl ich das Golang-Tutorial besucht habe, ist dies meine erste Interaktion mit der GO-Sprache, bitte entschuldigen Sie, dass ich Sie mit so vielen Zweifeln belästigt habe]
*.pb.*
Dateien bearbeiten. Diese werden automatisch aus den *.proto
Dateien generiert, wenn Sie mage proto:all
ausführen. Für die Zwecke dieser Ausgabe müssen jedoch keine derartigen Änderungen vorgenommen werden.Lassen Sie mich versuchen, die gesamte Pipeline besser zu erklären, vielleicht bringt dies etwas Licht in die Funktionsweise
*ttnpb.ApplicationUplink
.FRMPayload
Feld in die dekodierte Struktur von DecodedPayload
) unter Verwendung des Geräte-Payload-Formatierers.*ttnpb.ApplicationUp
und sendet es an die Frontends (MQTT, Webhooks, PubSub, Anwendungspakete).*ttnpb.ApplicationUp
und wählen basierend auf ihren Einstellungen (dem Format) den zu verwendenden Formatierer aus (die Formatiererschnittstelle ist in pkg/applicationserver/io/formatters
).formatter.FromUp
mit 1 *ttnph.ApplicationUp
und empfängt ein Stück Byte ( []byte
), das den Textkörper von 1 Nachricht darstellt.Was dieses Problem betrifft, hoffe ich, dass es sichtbar ist, dass nur Schritt 6 Änderungen erfordert:
FromUp
mehrere Nutzlasten (ein Stück von Byte-Slices) zurückgeben kann.Protobuf
und JSON
sollten ihr Verhalten nicht ändern und sollten daher weiterhin nur 1 Nutzlast zurückgeben (deshalb ist der Wrap erforderlich).[][]byte
Sie Fehler sehen (da die meisten Orte, die FromUp
aufrufen, nur eine Nutzlast empfangen - Sie müssen aktualisieren diese Aufrufstellen und lassen sie die Liste der Nutzlasten durchlaufen und jede von ihnen senden.Erst nachdem dieses Problem, das das Verhalten überhaupt nicht ändert, behoben wurde, können Sie mit der Implementierung Ihres eigenen Formatierers fortfahren, der einen Teil mehrerer Nutzdaten zurückgibt, einen für jede Messung (bedenken Sie jedoch, dass dieses neue Format ist für dieses Problem nicht relevant!).
Vielen Dank @adriansmares für diese ausführliche Erklärung und Anleitung. Ich glaube, ich habe es jetzt geschafft, dieses Problem zu lösen. Ich habe es auch mit ./mage go:test js:test jsSDK:test
getestet und es gibt keinen Fehler. Die wichtigsten Änderungen am Code sind im Folgenden hervorgehoben:
formatter.go
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
Das gleiche wie oben
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
Das gleiche wie oben
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
}
Bitte geben Sie Ihr Feedback und Ihre Kommentare. Ich werde die Korrekturen (Var-Benennung, Einrückung usw.) gemäß den Codestilrichtlinien vornehmen, sobald die Aufgabe vollständig abgeschlossen ist. Und wenn das richtig aussieht, könnten Sie mich bitte weiter für Ausgabe #1158 führen. Vielen Dank noch mal.
@mihir93 sieht gut aus! Bitte übernehmen Sie Ihre Änderungen und senden Sie einen Pull-Request für dieses Problem. Nach dem Zusammenführen können wir mit dem neuen Formatierer fortfahren, der in #1158 erwähnt wird.
@adriansmares Klar, das werde ich tun. Sollte dieser Pull Request auf der genannten Umgebung oder auf der neuesten Version des Stacks basieren?
Wir empfehlen Ihnen, Ihre Änderungen auf die neuesten master
umzubasieren, um spätere Konflikte zu vermeiden.
Dieses Problem ist seit einiger Zeit inaktiv, also verschieben wir es zurück in die Triage, um zu sehen, ob es noch Nachfrage dafür gibt oder ob wir es einfach fallen lassen sollten.
Dies wird nicht mehr benötigt, da es schlecht skaliert.